add test for recovering from backend disconnecting

This commit is contained in:
Andrew Kelley 2015-08-26 17:45:59 -07:00
parent b8a2adb4ec
commit d6e41672f7
5 changed files with 138 additions and 3 deletions

View file

@ -171,7 +171,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -pedantic")
set(LIB_CFLAGS "-std=c++11 -fno-exceptions -fno-rtti -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -Wno-c99-extensions")
set(EXAMPLE_CFLAGS "-std=c99 -Wall")
set(EXAMPLE_CFLAGS "-std=c11 -Wall")
set(EXAMPLE_INCLUDES "${CMAKE_SOURCE_DIR}/src")
set(TEST_CFLAGS "${LIB_CFLAGS} -fprofile-arcs -ftest-coverage")
set(TEST_LDFLAGS "-fprofile-arcs -ftest-coverage")
@ -289,6 +289,14 @@ include_directories(${EXAMPLE_INCLUDES})
target_link_libraries(underflow libsoundio_shared)
add_test(Underflow underflow)
add_executable(backend_disconnect_recover test/backend_disconnect_recover.c)
set_target_properties(backend_disconnect_recover PROPERTIES
LINKER_LANGUAGE C
COMPILE_FLAGS ${EXAMPLE_CFLAGS})
include_directories(${EXAMPLE_INCLUDES})
target_link_libraries(backend_disconnect_recover libsoundio_shared)
add_test(backend_disconnect_recover backend_disconnect_recover)
add_custom_target(coverage

View file

@ -258,6 +258,8 @@ For each backend, do the following:
0. Run `./sio_microphone` and ensure that it is both recording and playing
back correctly. If possible use the `--in-device` and `--out-device`
parameters to test a USB microphone in raw mode.
0. Run `./backend_disconnect_recover` and read the testing instructions that
it prints.
### Building the Documentation
@ -275,7 +277,6 @@ Then look at `html/index.html` in a browser.
0. Ability to "activate" a buffer-flexible outstream by jumping the gun and
causing `write_callback` to be called early.
- Use the same mechanism when destroying the outstream
0. Create a test for recovering from backend disconnecting that reconnects
0. Create a test for input stream overflow handling.
0. Create a test for the latency / synchronization API.
- Input is an audio file and some events indexed at particular frame - when

View file

@ -812,7 +812,8 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/example
EXAMPLE_PATH = "@CMAKE_SOURCE_DIR@/example" \
"@CMAKE_SOURCE_DIR@/test"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and

View file

@ -55,6 +55,10 @@
* Supports specifying device and backend to use.
*/
/** \example backend_disconnect_recover.c
* Demonstrates recovering from a backend disconnecting.
*/
/// See also ::soundio_strerror
enum SoundIoError {
SoundIoErrorNone,

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#include <soundio/soundio.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdatomic.h>
#include <unistd.h>
__attribute__ ((cold))
__attribute__ ((noreturn))
__attribute__ ((format (printf, 1, 2)))
static void panic(const char *format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
va_end(ap);
abort();
}
static int usage(char *exe) {
fprintf(stderr, "Usage: %s [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n", exe);
return 1;
}
static enum SoundIoBackend backend = SoundIoBackendNone;
static atomic_bool severed = ATOMIC_VAR_INIT(false);
static void on_backend_disconnect(struct SoundIo *soundio, int err) {
fprintf(stderr, "OK backend disconnected with '%s'.\n", soundio_strerror(err));
atomic_store(&severed, true);
soundio_wakeup(soundio);
}
int main(int argc, char **argv) {
char *exe = argv[0];
int timeout = 0;
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
if (arg[0] == '-' && arg[1] == '-') {
i += 1;
if (i >= argc) {
return usage(exe);
} else if (strcmp(arg, "--timeout") == 0) {
timeout = atoi(argv[i]);
} else if (strcmp(arg, "--backend") == 0) {
if (strcmp("-dummy", argv[i]) == 0) {
backend = SoundIoBackendDummy;
} else if (strcmp("alsa", argv[i]) == 0) {
backend = SoundIoBackendAlsa;
} else if (strcmp("pulseaudio", argv[i]) == 0) {
backend = SoundIoBackendPulseAudio;
} else if (strcmp("jack", argv[i]) == 0) {
backend = SoundIoBackendJack;
} else if (strcmp("coreaudio", argv[i]) == 0) {
backend = SoundIoBackendCoreAudio;
} else if (strcmp("wasapi", argv[i]) == 0) {
backend = SoundIoBackendWasapi;
} else {
fprintf(stderr, "Invalid backend: %s\n", argv[i]);
return 1;
}
} else {
return usage(exe);
}
} else {
return usage(exe);
}
}
struct SoundIo *soundio;
if (!(soundio = soundio_create()))
panic("out of memory");
int err = (backend == SoundIoBackendNone) ?
soundio_connect(soundio) : soundio_connect_backend(soundio, backend);
if (err)
panic("error connecting: %s", soundio_strerror(err));
soundio->on_backend_disconnect = on_backend_disconnect;
fprintf(stderr, "OK connected to %s. Now cause the backend to disconnect.\n",
soundio_backend_name(soundio->current_backend));
while (!atomic_load(&severed))
soundio_wait_events(soundio);
soundio_disconnect(soundio);
if (timeout > 0) {
fprintf(stderr, "OK sleeping for %d seconds\n", timeout);
sleep(timeout);
}
fprintf(stderr, "OK cleaned up. Reconnecting...\n");
err = (backend == SoundIoBackendNone) ?
soundio_connect(soundio) : soundio_connect_backend(soundio, backend);
if (err)
panic("error reconnecting: %s", soundio_strerror(err));
fprintf(stderr, "OK reconnected successfully to %s\n", soundio_backend_name(soundio->current_backend));
soundio_flush_events(soundio);
fprintf(stderr, "OK test passed\n");
return 0;
}