8f77395b58
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)
183 lines
3.9 KiB
C
183 lines
3.9 KiB
C
#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();
|
|
}
|