testing: add comprehensive test suite for test-driven development
CI / lint (push) Failing after 3s
CI / build-and-test (push) Has been skipped
CI / sanitizers (address) (push) Has been skipped
CI / coverage (push) Has been skipped
CI / valgrind (push) Has been skipped
CI / lint (pull_request) Failing after 2s
CI / build-and-test (pull_request) Has been skipped
CI / sanitizers (address) (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / valgrind (pull_request) Has been skipped

Add unit tests for previously untested modules (protocol, data, metadata,
file, glob), robustness tests for deserialization of malformed inputs,
thread safety stress tests, property-based roundtrip tests, and 6 fuzz
targets. Update CI with CTest integration, coverage reporting, and
valgrind memory checking.

New test files:
- test_data.c: Data type lifecycle (5 tests)
- test_protocol.c: Protocol I/O roundtrips and error paths (9 tests)
- test_metadata.c: Metadata serialization roundtrips (6 tests)
- test_file.c: File operations and send/receive (12 tests)
- test_glob.c: Glob pattern matching (10 tests)
- test_robustness.c: Malformed input handling for chunk/delta/protocol (11 tests)
- test_stress.c: MPMC queue stress, backpressure, rapid create/destroy (3 tests)
- test_property.c: Compress, delta, chunk, glob roundtrip properties (4 tests)
- tests/fuzz/: 6 libFuzzer targets for deserialization functions

Extended existing tests:
- test_config.c: config_send/config_receive roundtrip via fork+pipe
- test_shared_utils.c: mkdir_r, glob_match, delete_extras

Infrastructure:
- CTest integration in CMakeLists.txt
- Coverage support (-DENABLE_COVERAGE=ON)
- Fuzz target support (-DENABLE_FUZZ=ON)
- CI: coverage, valgrind, address sanitizer jobs
- Fixed MPMC stress test race condition (cnd_signal -> cnd_broadcast)
This commit is contained in:
2026-07-19 19:19:15 +02:00
parent 8a222bffa6
commit b179e6f6cf
25 changed files with 1560 additions and 7 deletions
+182
View File
@@ -0,0 +1,182 @@
#include "protocol.h"
#include "test_utils.h"
#include <limits.h>
#include <string.h>
#include <unistd.h>
static void test_send_receive_n_data() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
const char payload[] = "binary\x00test";
size_t len = sizeof(payload);
EXPECT_TRUE(send_n_data(0, payload, len));
char buf[64];
memset(buf, 0, sizeof(buf));
EXPECT_TRUE(receive_n_data(0, buf, len));
EXPECT_EQ_INT(memcmp(buf, payload, len), 0);
close(p[0]);
close(p[1]);
}
static void test_send_receive_n_data_zero() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
EXPECT_TRUE(send_n_data(0, "", 0));
char buf[4];
EXPECT_TRUE(receive_n_data(0, buf, 0));
close(p[0]);
close(p[1]);
}
static void test_send_receive_str() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
EXPECT_TRUE(send_str(0, ""));
char* received = receive_str(0);
EXPECT_NOT_NULL(received);
EXPECT_EQ_STR(received, "");
free(received);
close(p[0]);
close(p[1]);
}
static void test_send_receive_str_normal() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
EXPECT_TRUE(send_str(0, "Hello, Protocol!"));
char* received = receive_str(0);
EXPECT_NOT_NULL(received);
EXPECT_EQ_STR(received, "Hello, Protocol!");
free(received);
close(p[0]);
close(p[1]);
}
static void test_send_receive_data() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
unsigned char bin[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF};
void* buf = malloc(sizeof(bin));
EXPECT_NOT_NULL(buf);
memcpy(buf, bin, sizeof(bin));
Data* original = data_create(buf, sizeof(bin));
EXPECT_TRUE(send_data(0, original));
Data* received = receive_data(0);
EXPECT_NOT_NULL(received);
EXPECT_EQ_INT((int)received->size, (int)sizeof(bin));
EXPECT_EQ_INT(memcmp(received->data, bin, sizeof(bin)), 0);
data_destroy(original);
data_destroy(received);
close(p[0]);
close(p[1]);
}
static void test_send_receive_int() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
int val = 42;
EXPECT_TRUE(send_int(0, val));
int received = 0;
EXPECT_TRUE(receive_int(0, &received));
EXPECT_EQ_INT(received, 42);
val = 0;
EXPECT_TRUE(send_int(0, val));
EXPECT_TRUE(receive_int(0, &received));
EXPECT_EQ_INT(received, 0);
val = INT_MAX;
EXPECT_TRUE(send_int(0, val));
EXPECT_TRUE(receive_int(0, &received));
EXPECT_EQ_INT(received, INT_MAX);
close(p[0]);
close(p[1]);
}
static void test_send_receive_status() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
Status statuses[] = {STATUS_OK, STATUS_ERROR, STATUS_FINISHED, STATUS_NEXT,
STATUS_CHUNK, STATUS_CHECK, STATUS_DELTA_SIGNATURE, STATUS_DELTA_DATA};
int count = sizeof(statuses) / sizeof(statuses[0]);
for (int i = 0; i < count; i++) {
EXPECT_TRUE(send_status(0, statuses[i]));
Status received = -1;
EXPECT_TRUE(receive_status(0, &received));
EXPECT_EQ_INT((int)received, (int)statuses[i]);
}
close(p[0]);
close(p[1]);
}
static void test_receive_n_data_truncated() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
close(p[1]);
char buf[32];
EXPECT_FALSE(receive_n_data(0, buf, 32));
close(p[0]);
}
static void test_receive_str_truncated() {
int p[2];
EXPECT_EQ_INT(pipe(p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
close(p[1]);
char* received = receive_str(0);
EXPECT_NULL(received);
close(p[0]);
}
void test_protocol() {
test_send_receive_n_data();
test_send_receive_n_data_zero();
test_send_receive_str();
test_send_receive_str_normal();
test_send_receive_data();
test_send_receive_int();
test_send_receive_status();
test_receive_n_data_truncated();
test_receive_str_truncated();
}