refactor: split transfer and protocol responsibilities
CI / lint (pull_request) Failing after 30s
CI / build-and-test (pull_request) Has been skipped
CI / sanitizers (address) (pull_request) Has been skipped
CI / sanitizers (undefined) (pull_request) Has been skipped
CI / fuzz-build (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / valgrind (pull_request) Has been skipped
CI / lint (pull_request) Failing after 30s
CI / build-and-test (pull_request) Has been skipped
CI / sanitizers (address) (pull_request) Has been skipped
CI / sanitizers (undefined) (pull_request) Has been skipped
CI / fuzz-build (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / valgrind (pull_request) Has been skipped
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "test_client_cli.h"
|
||||
#include "client_validation.h"
|
||||
#include "config.h"
|
||||
#include "test_utils.h"
|
||||
#include "utils.h"
|
||||
@@ -9,6 +10,56 @@
|
||||
/* Declaration of parse_args from client_cli.c */
|
||||
int parse_args(Config* config, int argc, char* argv[], int* positional_args, int* positional_count);
|
||||
|
||||
static Config* valid_client_config() {
|
||||
Config* cfg = config_create();
|
||||
if (!cfg)
|
||||
return NULL;
|
||||
cfg->send_directory = str_dup("/src");
|
||||
cfg->receive_root_directory = str_dup("/dst");
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static void test_validate_config_required_paths() {
|
||||
Config* cfg = config_create();
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
cfg->send_directory = str_dup("/src");
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
static void test_validate_config_incompatible_options() {
|
||||
Config* cfg = valid_client_config();
|
||||
cfg->use_sendfile = true;
|
||||
cfg->use_compression = true;
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
cfg->use_compression = false;
|
||||
cfg->use_incremental = true;
|
||||
cfg->use_chunk_serialization = true;
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
static void test_validate_config_tls_requirements() {
|
||||
Config* cfg = valid_client_config();
|
||||
cfg->use_tls = true;
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
cfg->tls_cert = str_dup("cert.pem");
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
cfg->tls_key = str_dup("key.pem");
|
||||
EXPECT_TRUE(validate_config(cfg));
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
static void test_validate_config_delta_sendfile_constraints() {
|
||||
Config* cfg = valid_client_config();
|
||||
cfg->use_delta = true;
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
cfg->use_incremental = true;
|
||||
cfg->use_sendfile = true;
|
||||
EXPECT_FALSE(validate_config(cfg));
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
/* Test main() with --help flag (early return path, no server connection needed) */
|
||||
static void test_cli_help() {
|
||||
/* We can't easily call main() because it calls send_files which needs a server.
|
||||
@@ -287,6 +338,10 @@ static void test_parse_args_archive() {
|
||||
}
|
||||
|
||||
void test_client_cli() {
|
||||
test_validate_config_required_paths();
|
||||
test_validate_config_incompatible_options();
|
||||
test_validate_config_tls_requirements();
|
||||
test_validate_config_delta_sendfile_constraints();
|
||||
test_cli_help();
|
||||
test_cli_archive_flags();
|
||||
test_cli_dry_run();
|
||||
|
||||
@@ -224,6 +224,26 @@ static void test_config_send_receive_version_mismatch() {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_config_receive_truncated() {
|
||||
int p[2];
|
||||
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
|
||||
io_set_fds(p[0], p[0]);
|
||||
io_set_bwlimit(0);
|
||||
|
||||
/* A valid prefix exercises cleanup after allocated wire strings and a
|
||||
* partially received scalar field. */
|
||||
EXPECT_TRUE(send_str(p[1], PROTOCOL_VERSION));
|
||||
EXPECT_TRUE(send_str(p[1], "/src"));
|
||||
EXPECT_TRUE(send_str(p[1], "/dst"));
|
||||
EXPECT_TRUE(send_int(p[1], 1));
|
||||
shutdown(p[1], SHUT_WR);
|
||||
|
||||
Config* cfg = config_receive(p[0]);
|
||||
EXPECT_NULL(cfg);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
static void test_is_remote_dest() {
|
||||
/* Valid SSH-style destinations */
|
||||
EXPECT_TRUE(is_remote_dest("user@host:/path"));
|
||||
@@ -256,6 +276,7 @@ void test_config() {
|
||||
if (!is_running_under_valgrind()) {
|
||||
test_config_send_receive();
|
||||
test_config_send_receive_version_mismatch();
|
||||
test_config_receive_truncated();
|
||||
}
|
||||
test_is_remote_dest();
|
||||
}
|
||||
|
||||
@@ -38,6 +38,23 @@ static void test_send_receive_n_data_zero() {
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
static void test_explicit_session_context() {
|
||||
int p[2];
|
||||
EXPECT_EQ_INT(pipe(p), 0);
|
||||
ProtocolSession session;
|
||||
protocol_session_init(&session, p[0], p[1]);
|
||||
protocol_session_set_bwlimit(&session, 0);
|
||||
|
||||
const char payload[] = "explicit context";
|
||||
char received[sizeof(payload)] = {0};
|
||||
EXPECT_TRUE(protocol_send_n_data(&session, payload, sizeof(payload)));
|
||||
EXPECT_TRUE(protocol_receive_n_data(&session, received, sizeof(received)));
|
||||
EXPECT_EQ_INT(memcmp(payload, received, sizeof(payload)), 0);
|
||||
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
static void test_send_receive_str() {
|
||||
int p[2];
|
||||
EXPECT_EQ_INT(pipe(p), 0);
|
||||
@@ -173,6 +190,7 @@ static void test_receive_str_truncated() {
|
||||
void test_protocol() {
|
||||
test_send_receive_n_data();
|
||||
test_send_receive_n_data_zero();
|
||||
test_explicit_session_context();
|
||||
test_send_receive_str();
|
||||
test_send_receive_str_normal();
|
||||
test_send_receive_data();
|
||||
|
||||
+4
-8
@@ -11,11 +11,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include server.c but rename main to avoid conflict with test runner's main */
|
||||
#define main server_main_
|
||||
#define FASTSYNC_SERVER_AS_LIB
|
||||
#include "server.c"
|
||||
#undef main
|
||||
#include "receiver.h"
|
||||
|
||||
/* Test receive_files with immediate FINISHED status */
|
||||
static void test_receive_files_finished() {
|
||||
@@ -36,7 +32,7 @@ static void test_receive_files_finished() {
|
||||
/* Child: use p[0] for both read and write */
|
||||
close(p[1]);
|
||||
io_set_fds(p[0], p[0]);
|
||||
int ret = receive_files(cfg, p[0]);
|
||||
int ret = receiver_receive_files(cfg, p[0]);
|
||||
close(p[0]);
|
||||
config_delete(cfg);
|
||||
_exit(ret == 0 ? 0 : 1);
|
||||
@@ -88,7 +84,7 @@ static void test_receive_files_single_file() {
|
||||
/* Child: use p[0] for both read and write */
|
||||
close(p[1]);
|
||||
io_set_fds(p[0], p[0]);
|
||||
int ret = receive_files(cfg, p[0]);
|
||||
int ret = receiver_receive_files(cfg, p[0]);
|
||||
close(p[0]);
|
||||
config_delete(cfg);
|
||||
_exit(ret == 0 ? 0 : 1);
|
||||
@@ -149,7 +145,7 @@ static void test_receive_files_abort() {
|
||||
if (pid == 0) {
|
||||
close(p[1]);
|
||||
io_set_fds(p[0], p[0]);
|
||||
int ret = receive_files(cfg, p[0]);
|
||||
int ret = receiver_receive_files(cfg, p[0]);
|
||||
close(p[0]);
|
||||
config_delete(cfg);
|
||||
/* Should return -1 on abort */
|
||||
|
||||
Reference in New Issue
Block a user