4-implement-scene-switching-engine #4
32
tests/main.c
Normal file
32
tests/main.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "test_common.h"
|
||||
|
||||
/* Declare test group functions */
|
||||
int test_audio(void);
|
||||
int test_loop(void);
|
||||
int test_channel(void);
|
||||
int test_scene_all(void);
|
||||
int test_fifo(void);
|
||||
|
||||
int main(void) {
|
||||
if (system("test -x ./looper") != 0) {
|
||||
fprintf(stderr, "FATAL: looper binary not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int failures = 0;
|
||||
|
||||
/* Audio pass‑through (non‑fatal) */
|
||||
test_audio();
|
||||
|
||||
failures += test_loop();
|
||||
failures += test_channel();
|
||||
failures += test_scene_all();
|
||||
failures += test_fifo();
|
||||
|
||||
if (failures > 0) {
|
||||
fprintf(stderr, "%d test(s) FAILED\n", failures);
|
||||
return 1;
|
||||
}
|
||||
printf("All tests completed successfully.\n");
|
||||
return 0;
|
||||
}
|
||||
89
tests/test_audio.c
Normal file
89
tests/test_audio.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "test_common.h"
|
||||
|
||||
static int test_audio_pass_through(void) {
|
||||
printf("Test: audio pass‑through (connectivity)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_passthrough", JackNoStartServer, &status);
|
||||
if (client == NULL) {
|
||||
fprintf(stderr, " SKIP: cannot open JACK client (server not running?)\n");
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *output_port = jack_port_register(client, "output",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *input_port = jack_port_register(client, "input",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!output_port || !input_port) {
|
||||
fprintf(stderr, " FAIL: could not register ports\n");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
const char *looper_input = "looper:input";
|
||||
const char *looper_output = "looper:output";
|
||||
char my_output[64], my_input[64];
|
||||
snprintf(my_output, sizeof(my_output), "test_passthrough:output");
|
||||
snprintf(my_input, sizeof(my_input), "test_passthrough:input");
|
||||
if (jack_connect(client, my_output, looper_input) != 0) {
|
||||
fprintf(stderr, " FAIL: cannot connect\n");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (jack_connect(client, looper_output, my_input) != 0) {
|
||||
fprintf(stderr, " FAIL: cannot connect\n");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
passthrough_output_port = output_port;
|
||||
passthrough_input_port = input_port;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = jack_get_sample_rate(client);
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
continuous_sine = 1;
|
||||
beep_remaining = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client) != 0) {
|
||||
fprintf(stderr, " FAIL: cannot activate client\n");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(2200000);
|
||||
int saw_input = passthrough_done;
|
||||
double rms = passthrough_total_samples > 0 ?
|
||||
sqrt(passthrough_sum_sq / passthrough_total_samples) : 0.0;
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (!saw_input) {
|
||||
fprintf(stderr, " FAIL: looper did not produce output (no callback run?)\n");
|
||||
return 1;
|
||||
}
|
||||
if (rms < 0.001) {
|
||||
fprintf(stderr, " FAIL: looper output RMS too small (%.6f)\n", rms);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (RMS %.6f)\n", rms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_audio(void) {
|
||||
return test_audio_pass_through();
|
||||
}
|
||||
611
tests/test_channel.c
Normal file
611
tests/test_channel.c
Normal file
@@ -0,0 +1,611 @@
|
||||
#include "test_common.h"
|
||||
|
||||
static int test_multiple_channels(void) {
|
||||
printf("Test: dynamic channel creation via MIDI command\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_multi", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 60, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int found = 0;
|
||||
for (int retries = 0; retries < 30; retries++) {
|
||||
safe_usleep(100000);
|
||||
const char **ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0);
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_input")) {
|
||||
found = 1;
|
||||
jack_free(ports);
|
||||
goto port_found;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
}
|
||||
port_found:
|
||||
;
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (!found) {
|
||||
fprintf(stderr, " FAIL: channel1_input port not created\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (channel created)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_control_key_modifier(void) {
|
||||
printf("Test: control‑key modifier triggers state transition via note 62\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_ctrl_key", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_ctrl_key:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_ctrl_key:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.1f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(2000000);
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
int got_bursts = bursts;
|
||||
printf(" detected bursts: %d\n", got_bursts);
|
||||
if (got_bursts < 3) {
|
||||
fprintf(stderr, " FAIL: expected ≥3 bursts, got %d\n", got_bursts);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (control‑key modifier works)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_bind_channel(void) {
|
||||
printf("Test: control‑key bind channel (note 0) and toggle\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_bind", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_bind:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_bind:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 0, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.1f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(2000000);
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
int got_bursts = bursts;
|
||||
printf(" detected bursts: %d\n", got_bursts);
|
||||
if (got_bursts < 3) {
|
||||
fprintf(stderr, " FAIL: expected >=3 bursts, got %d\n", got_bursts);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (bind and toggle)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_bind_unbind(void) {
|
||||
printf("Test: bind to channel 5, unbind, then toggle default (channel 0)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_unbind", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_unbind:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_unbind:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 5, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 63, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.1f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 62, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(2000000);
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
int got_bursts = bursts;
|
||||
printf(" detected bursts: %d\n", got_bursts);
|
||||
if (got_bursts < 3) {
|
||||
fprintf(stderr, " FAIL: expected >=3 bursts, got %d\n", got_bursts);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (unbind works, toggle channel 0)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_remove_channel(void) {
|
||||
printf("Test: dynamic channel removal via MIDI command\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_remove", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 60, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(1500000);
|
||||
const char **ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0);
|
||||
int found = 0;
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_input")) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
if (!found) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: channel1_input not created\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" channel1_input created\n");
|
||||
if (send_jack_note_on("looper:control", 61, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int still_found = 1;
|
||||
for (int retries = 0; retries < 30; retries++) {
|
||||
safe_usleep(100000);
|
||||
ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0);
|
||||
still_found = 0;
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_input")) {
|
||||
still_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
if (!still_found) break;
|
||||
}
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (still_found) {
|
||||
fprintf(stderr, " FAIL: channel1_input not removed after remove command\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (channel removed)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_stop_midi(void) {
|
||||
printf("Test: MIDI stop (note 65 under control key)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_stop", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_stop:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_stop:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.2f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(150000);
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(500000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 65, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
int prev = bursts;
|
||||
for (int retries = 0; retries < 20; retries++) {
|
||||
safe_usleep(100000);
|
||||
int cur = bursts;
|
||||
if (cur == prev) break;
|
||||
prev = cur;
|
||||
}
|
||||
int bursts_before = bursts;
|
||||
safe_usleep(500000);
|
||||
int bursts_after = bursts;
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (bursts_after > bursts_before + 5) {
|
||||
fprintf(stderr, " FAIL: bursts continued after stop (%d -> %d)\n",
|
||||
bursts_before, bursts_after);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (stop stopped playback)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_midi_channel_add(void) {
|
||||
printf("Test: MIDI channel creation via FIFO (add_midi)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_midi_add", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
int fd = open("/tmp/looper_cmd", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("open fifo");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
write(fd, "add_midi\n", 9);
|
||||
close(fd);
|
||||
safe_usleep(1500000);
|
||||
const char **ports = jack_get_ports(client, NULL, JACK_DEFAULT_MIDI_TYPE, 0);
|
||||
int found = 0;
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_midi_in")) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (!found) {
|
||||
fprintf(stderr, " FAIL: channel1_midi_in port not created\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (MIDI channel created)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_channel(void) {
|
||||
int failures = 0;
|
||||
failures += test_multiple_channels();
|
||||
failures += test_control_key_modifier();
|
||||
failures += test_bind_channel();
|
||||
failures += test_bind_unbind();
|
||||
failures += test_remove_channel();
|
||||
failures += test_stop_midi();
|
||||
failures += test_midi_channel_add();
|
||||
return failures;
|
||||
}
|
||||
160
tests/test_fifo.c
Normal file
160
tests/test_fifo.c
Normal file
@@ -0,0 +1,160 @@
|
||||
#include "test_common.h"
|
||||
|
||||
static int test_fifo_pipe(void) {
|
||||
printf("Test: FIFO pipe add/remove\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_fifo", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
int fd = open("/tmp/looper_cmd", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("open fifo");
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
write(fd, "add\n", 4);
|
||||
safe_usleep(1500000);
|
||||
const char **ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0);
|
||||
int found = 0;
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_input")) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
write(fd, "remove\n", 7);
|
||||
close(fd);
|
||||
safe_usleep(1500000);
|
||||
ports = jack_get_ports(client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0);
|
||||
int still_found = 0;
|
||||
if (ports) {
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
if (strstr(ports[i], "looper:channel1_input")) {
|
||||
still_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
jack_free(ports);
|
||||
}
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (!found) {
|
||||
fprintf(stderr, " FAIL: channel not added via FIFO\n");
|
||||
return 1;
|
||||
}
|
||||
if (still_found) {
|
||||
fprintf(stderr, " FAIL: channel not removed via FIFO\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (FIFO add/remove works)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_fifo_stop_bind_unbind(void) {
|
||||
printf("Test: FIFO stop, bind, unbind\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_fifo_stop", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_fifo_stop:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_fifo_stop:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.1f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(150000);
|
||||
int fd = open("/tmp/looper_cmd", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("open fifo");
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
write(fd, "stop\n", 5);
|
||||
write(fd, "bind 0\n", 7);
|
||||
write(fd, "unbind\n", 7);
|
||||
close(fd);
|
||||
safe_usleep(500000);
|
||||
int bursts_after = bursts;
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (bursts_after < 1) {
|
||||
fprintf(stderr, " FAIL: no burst detected (probably no recording)\n");
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (FIFO stop, bind, unbind executed)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_fifo(void) {
|
||||
int failures = 0;
|
||||
failures += test_fifo_pipe();
|
||||
failures += test_fifo_stop_bind_unbind();
|
||||
return failures;
|
||||
}
|
||||
190
tests/test_loop.c
Normal file
190
tests/test_loop.c
Normal file
@@ -0,0 +1,190 @@
|
||||
#include "test_common.h"
|
||||
|
||||
static int test_looper_looping(void) {
|
||||
printf("Test: loop recording and playback (expect ≥3 repetitions)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_looping", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: JACK not running?\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_looping:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_looping:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(500000);
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.1f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(150000);
|
||||
safe_usleep(800000);
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(4000000);
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
int got_bursts = bursts;
|
||||
printf(" detected bursts: %d\n", got_bursts);
|
||||
if (got_bursts < 3) {
|
||||
fprintf(stderr, " FAIL: expected ≥3 bursts, got %d\n", got_bursts);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (at least 3 repetitions)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_record_loop_stop(void) {
|
||||
printf("Test: full record‑loop‑stop (≥5 repetitions)\n");
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
if (init_persistent_midi_client() != 0) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot initialise persistent MIDI client\n");
|
||||
return 1;
|
||||
}
|
||||
jack_client_t *client;
|
||||
jack_status_t status;
|
||||
client = jack_client_open("test_full", JackNoStartServer, &status);
|
||||
if (!client) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " SKIP: no JACK\n");
|
||||
return 1;
|
||||
}
|
||||
jack_port_t *audio_out = jack_port_register(client, "out",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
jack_port_t *audio_in = jack_port_register(client, "in",
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput, 0);
|
||||
if (!audio_out || !audio_in) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
char my_out[64], my_in[64];
|
||||
snprintf(my_out, sizeof(my_out), "test_full:out");
|
||||
snprintf(my_in, sizeof(my_in), "test_full:in");
|
||||
if (jack_connect(client, my_out, "looper:input") ||
|
||||
jack_connect(client, "looper:output", my_in)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(500000);
|
||||
int sr = jack_get_sample_rate(client);
|
||||
continuous_sine = 0;
|
||||
beep_remaining = (int)(0.5f * sr);
|
||||
bursts = 0;
|
||||
prev_above = 0;
|
||||
passthrough_output_port = audio_out;
|
||||
passthrough_input_port = audio_in;
|
||||
passthrough_phase = 0.0f;
|
||||
passthrough_freq = 440.0f;
|
||||
passthrough_sample_rate = sr;
|
||||
passthrough_total_samples = 0;
|
||||
passthrough_sum_sq = 0.0;
|
||||
passthrough_done = 0;
|
||||
jack_set_process_callback(client, passthrough_process, NULL);
|
||||
if (jack_activate(client)) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 1, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(2500000);
|
||||
if (send_jack_note_on("looper:control", 64, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
if (send_jack_note_on("looper:control", 65, 127) != 0) {
|
||||
jack_client_close(client);
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(200000);
|
||||
int total_bursts = bursts;
|
||||
jack_deactivate(client);
|
||||
jack_client_close(client);
|
||||
cleanup_persistent_midi_client();
|
||||
kill(pid, SIGTERM);
|
||||
waitpid(pid, NULL, 0);
|
||||
if (total_bursts < 5) {
|
||||
fprintf(stderr, " FAIL: expected ≥5 bursts, got %d\n", total_bursts);
|
||||
return 1;
|
||||
}
|
||||
printf(" PASS (≥5 repetitions, stopped cleanly)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_loop(void) {
|
||||
int failures = 0;
|
||||
failures += test_looper_looping();
|
||||
failures += test_record_loop_stop();
|
||||
return failures;
|
||||
}
|
||||
Reference in New Issue
Block a user