feat: add integration test framework and rack/grid command support
This commit is contained in:
committed by
Loic Coenen (aider)
parent
9fda1b2669
commit
e6e0a47749
@@ -13,6 +13,7 @@ TEST_PLUGINS_BIN = test_plugins
|
|||||||
TEST_CLIENT_BIN = test_client
|
TEST_CLIENT_BIN = test_client
|
||||||
TEST_CARLA_BIN = test_carla_host
|
TEST_CARLA_BIN = test_carla_host
|
||||||
TEST_CLIENT_CMD_BIN = test_client_cmd
|
TEST_CLIENT_CMD_BIN = test_client_cmd
|
||||||
|
TEST_INTEGRATION_BIN = test_integration
|
||||||
|
|
||||||
all: looper-client test_status_parse
|
all: looper-client test_status_parse
|
||||||
|
|
||||||
@@ -29,6 +30,11 @@ $(PLUGINS_OBJ): src/plugins.c src/plugins.h
|
|||||||
$(CARLA_OBJ): src/carla_host.c src/carla_host.h
|
$(CARLA_OBJ): src/carla_host.c src/carla_host.h
|
||||||
$(CC) -Wall -Wextra -std=c11 -Isrc $(CARLA_INC) -c -o $@ $<
|
$(CC) -Wall -Wextra -std=c11 -Isrc $(CARLA_INC) -c -o $@ $<
|
||||||
|
|
||||||
|
CARLA_TEST_OBJ = src/carla_host_test.o
|
||||||
|
|
||||||
|
$(CARLA_TEST_OBJ): src/carla_host.c src/carla_host.h
|
||||||
|
$(CC) -Wall -Wextra -std=c11 -Isrc $(CARLA_INC) -DTESTING -c -o $@ $<
|
||||||
|
|
||||||
$(CLIENT_CMD_OBJ): src/client_cmd.c src/client_cmd.h
|
$(CLIENT_CMD_OBJ): src/client_cmd.c src/client_cmd.h
|
||||||
$(CC) $(CFLAGS) $(CARLA_INC) -c -o $@ $<
|
$(CC) $(CFLAGS) $(CARLA_INC) -c -o $@ $<
|
||||||
|
|
||||||
@@ -71,14 +77,19 @@ $(TEST_CARLA_OBJ): tests/test_carla_host.c src/carla_host.h
|
|||||||
$(TEST_CARLA_BIN): $(TEST_CARLA_OBJ) $(CARLA_OBJ)
|
$(TEST_CARLA_BIN): $(TEST_CARLA_OBJ) $(CARLA_OBJ)
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(CARLA_LIB) -ljack
|
$(CC) $(CFLAGS) -o $@ $^ $(CARLA_LIB) -ljack
|
||||||
|
|
||||||
test: looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN)
|
# --- Integration test (requires TESTING symbol) ---
|
||||||
|
$(TEST_INTEGRATION_BIN): tests/test_integration.c $(CARLA_TEST_OBJ)
|
||||||
|
$(CC) $(CFLAGS) $(CARLA_INC) -DTESTING -o $@ $^ $(CARLA_LIB) -ljack
|
||||||
|
|
||||||
|
test: looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN)
|
||||||
./test_status_parse
|
./test_status_parse
|
||||||
./$(TEST_PLUGINS_BIN)
|
./$(TEST_PLUGINS_BIN)
|
||||||
./$(TEST_CLIENT_BIN)
|
./$(TEST_CLIENT_BIN)
|
||||||
./$(TEST_CARLA_BIN)
|
./$(TEST_CARLA_BIN)
|
||||||
./$(TEST_CLIENT_CMD_BIN)
|
./$(TEST_CLIENT_CMD_BIN)
|
||||||
|
./$(TEST_INTEGRATION_BIN)
|
||||||
|
|
||||||
.PHONY: all test clean
|
.PHONY: all test clean
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) *.o tests/*.o src/*.o
|
rm -f looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN) *.o tests/*.o src/*.o
|
||||||
|
|||||||
@@ -173,6 +173,27 @@ int carla_disconnect_plugin(int id) {
|
|||||||
return any ? 0 : -1; // return -1 if no connections were found (harmless)
|
return any ? 0 : -1; // return -1 if no connections were found (harmless)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
int carla_test_connection_count(void) {
|
||||||
|
return conn_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int carla_test_add_connection(int plugin_id, const char *plugin_port, const char *looper_port) {
|
||||||
|
if (!plugin_port || !looper_port) return -1;
|
||||||
|
if (conn_count >= MAX_CONNECTIONS) return -1;
|
||||||
|
|
||||||
|
strncpy(connections[conn_count].plugin_port, plugin_port,
|
||||||
|
sizeof(connections[conn_count].plugin_port) - 1);
|
||||||
|
connections[conn_count].plugin_port[sizeof(connections[conn_count].plugin_port) - 1] = '\0';
|
||||||
|
strncpy(connections[conn_count].looper_port, looper_port,
|
||||||
|
sizeof(connections[conn_count].looper_port) - 1);
|
||||||
|
connections[conn_count].looper_port[sizeof(connections[conn_count].looper_port) - 1] = '\0';
|
||||||
|
connections[conn_count].plugin_id = plugin_id;
|
||||||
|
conn_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CarlaHostHandle carla_get_handle(void) {
|
CarlaHostHandle carla_get_handle(void) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,9 @@ void carla_set_bypass(int id, bool bypass);
|
|||||||
int carla_disconnect_plugin(int id);
|
int carla_disconnect_plugin(int id);
|
||||||
CarlaHostHandle carla_get_handle(void);
|
CarlaHostHandle carla_get_handle(void);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
int carla_test_connection_count(void);
|
||||||
|
int carla_test_add_connection(int plugin_id, const char *plugin_port, const char *looper_port);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -235,6 +235,19 @@ void tui_run(void) {
|
|||||||
colon_buf[colon_len] = '\0';
|
colon_buf[colon_len] = '\0';
|
||||||
colon_len = 0;
|
colon_len = 0;
|
||||||
in_colon = false;
|
in_colon = false;
|
||||||
|
// Check first token before calling handle_client_command
|
||||||
|
char cmd_copy[256];
|
||||||
|
strncpy(cmd_copy, colon_buf, sizeof(cmd_copy)-1);
|
||||||
|
cmd_copy[sizeof(cmd_copy)-1] = '\0';
|
||||||
|
char *first = strtok(cmd_copy, " ");
|
||||||
|
if (first) {
|
||||||
|
if (strcmp(first, "rack") == 0) {
|
||||||
|
rack_mode = true;
|
||||||
|
rack_selected = 0;
|
||||||
|
} else if (strcmp(first, "grid") == 0) {
|
||||||
|
rack_mode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
int dummy_id;
|
int dummy_id;
|
||||||
handle_client_command(colon_buf, &dummy_id);
|
handle_client_command(colon_buf, &dummy_id);
|
||||||
draw_grid();
|
draw_grid();
|
||||||
|
|||||||
@@ -26,6 +26,57 @@ static int tests_failed = 0;
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
/* Test from command */
|
||||||
|
static void test_from_store(void)
|
||||||
|
{
|
||||||
|
int ret = handle_client_command("from looper:out_0", NULL);
|
||||||
|
ASSERT_EQ(0, ret, "handle_client_command('from looper:out_0', NULL) returns 0");
|
||||||
|
const char *stored = get_stored_from();
|
||||||
|
ASSERT_STR_EQ("looper:out_0", stored, "get_stored_from() returns 'looper:out_0'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test to command */
|
||||||
|
static void test_to_store(void)
|
||||||
|
{
|
||||||
|
int ret = handle_client_command("to plugin:in", NULL);
|
||||||
|
ASSERT_EQ(0, ret, "handle_client_command('to plugin:in', NULL) returns 0");
|
||||||
|
const char *stored = get_stored_to();
|
||||||
|
ASSERT_STR_EQ("plugin:in", stored, "get_stored_to() returns 'plugin:in'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test connect using stored from/to (should call plugin_connect with those ports, fail because no plugin) */
|
||||||
|
static void test_connect_uses_stored(void)
|
||||||
|
{
|
||||||
|
/* Ensure stored from and to are set */
|
||||||
|
handle_client_command("from looper:out_0", NULL);
|
||||||
|
handle_client_command("to plugin:in", NULL);
|
||||||
|
int id = -1;
|
||||||
|
int ret = handle_client_command("connect", &id);
|
||||||
|
/* Should return -1 because plugin_connect fails (no plugin loaded), but not -1 from missing args */
|
||||||
|
ASSERT_EQ(-1, ret, "handle_client_command('connect', ...) returns -1 when plugin_connect fails (no JACK)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test disconnect using stored from/to */
|
||||||
|
static void test_disconnect_uses_stored(void)
|
||||||
|
{
|
||||||
|
handle_client_command("from looper:out_0", NULL);
|
||||||
|
handle_client_command("to plugin:in", NULL);
|
||||||
|
int id = -1;
|
||||||
|
int ret = handle_client_command("disconnect", &id);
|
||||||
|
/* plugin_disconnect returns 0 even without JACK, so we expect 0 */
|
||||||
|
ASSERT_EQ(0, ret, "handle_client_command('disconnect', ...) returns 0 (safe stub)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test rack/grid commands return 0 */
|
||||||
|
static void test_rack_grid_commands(void)
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
int ret = handle_client_command("rack", &id);
|
||||||
|
ASSERT_EQ(0, ret, "handle_client_command('rack', ...) returns 0");
|
||||||
|
ret = handle_client_command("grid", &id);
|
||||||
|
ASSERT_EQ(0, ret, "handle_client_command('grid', ...) returns 0");
|
||||||
|
}
|
||||||
|
|
||||||
/* Test invalid commands */
|
/* Test invalid commands */
|
||||||
static void test_unknown_command(void)
|
static void test_unknown_command(void)
|
||||||
{
|
{
|
||||||
@@ -105,6 +156,11 @@ int main(void)
|
|||||||
test_connect_no_args();
|
test_connect_no_args();
|
||||||
test_connect_missing_to();
|
test_connect_missing_to();
|
||||||
test_connect_invalid_id();
|
test_connect_invalid_id();
|
||||||
|
test_from_store();
|
||||||
|
test_to_store();
|
||||||
|
test_connect_uses_stored();
|
||||||
|
test_disconnect_uses_stored();
|
||||||
|
test_rack_grid_commands();
|
||||||
|
|
||||||
printf("\nResults: %d passed, %d failed\n", tests_passed, tests_failed);
|
printf("\nResults: %d passed, %d failed\n", tests_passed, tests_failed);
|
||||||
return tests_failed > 0 ? 1 : 0;
|
return tests_failed > 0 ? 1 : 0;
|
||||||
|
|||||||
35
client/tests/test_integration.c
Normal file
35
client/tests/test_integration.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#define TESTING 1
|
||||||
|
#include "carla_host.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("=== Integration test (requires JACK server) ===\n");
|
||||||
|
|
||||||
|
/* Fail if no JACK server */
|
||||||
|
if (carla_init_jack() != 0) {
|
||||||
|
fprintf(stderr, "FAIL: cannot initialise Carla/JACK – is the JACK server running?\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify handle is now non‑NULL */
|
||||||
|
CarlaHostHandle h = carla_get_handle();
|
||||||
|
assert(h != NULL);
|
||||||
|
|
||||||
|
/* Test connection tracking without loading a real plugin.
|
||||||
|
carla_test_add_connection adds a fake connection entry. */
|
||||||
|
int ret = carla_test_add_connection(0, "test:out", "looper:in");
|
||||||
|
assert(ret == 0);
|
||||||
|
assert(carla_test_connection_count() == 1);
|
||||||
|
|
||||||
|
/* Disconnect plugin ID 0 – should clear the list */
|
||||||
|
ret = carla_disconnect_plugin(0);
|
||||||
|
assert(ret == 0);
|
||||||
|
assert(carla_test_connection_count() == 0);
|
||||||
|
|
||||||
|
carla_cleanup_jack();
|
||||||
|
|
||||||
|
printf("PASS: all integration tests passed (with JACK server).\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user