#include "test_client_cli.h" #include "config.h" #include "test_utils.h" #include "utils.h" #include #include #include /* Declaration of parse_args from client_cli.c */ int parse_args(Config* config, int argc, char* argv[], int* positional_args, int* positional_count); /* 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. * Instead, test the argument parsing logic by testing that config_create works * with the same parameters client_cli uses, and that config_delete cleans up * properly when send_directory and receive_root_directory are NULL. */ /* This matches what client_cli does at startup */ Config* cfg = config_create(); EXPECT_NOT_NULL(cfg); EXPECT_NULL(cfg->send_directory); EXPECT_NULL(cfg->receive_root_directory); EXPECT_FALSE(cfg->save_to_disk); EXPECT_EQ_INT(cfg->compression_level, 5); config_delete(cfg); } /* Test that --archive sets compression, multithreading, and metadata */ static void test_cli_archive_flags() { Config* cfg = config_create(); EXPECT_NOT_NULL(cfg); /* Simulate --archive flag */ cfg->use_compression = true; cfg->use_multithreading = true; cfg->use_metadata = true; EXPECT_TRUE(cfg->use_compression); EXPECT_TRUE(cfg->use_multithreading); EXPECT_TRUE(cfg->use_metadata); config_delete(cfg); } /* Test that --dry-run sets dry_run flag */ static void test_cli_dry_run() { Config* cfg = config_create(); cfg->dry_run = true; EXPECT_TRUE(cfg->dry_run); config_delete(cfg); } /* Test that --delete sets use_delete */ static void test_cli_delete_flag() { Config* cfg = config_create(); cfg->use_delete = true; EXPECT_TRUE(cfg->use_delete); config_delete(cfg); } /* Test exclude pattern handling */ static void test_cli_exclude_patterns() { Config* cfg = config_create(); EXPECT_NOT_NULL(cfg); /* Simulate --exclude "*.log" --exclude "tmp/" */ cfg->exclude_patterns = malloc(2 * sizeof(char*)); EXPECT_NOT_NULL(cfg->exclude_patterns); cfg->exclude_patterns[0] = str_dup("*.log"); cfg->exclude_patterns[1] = str_dup("tmp/"); cfg->exclude_count = 2; EXPECT_EQ_STR(cfg->exclude_patterns[0], "*.log"); EXPECT_EQ_STR(cfg->exclude_patterns[1], "tmp/"); EXPECT_EQ_INT(cfg->exclude_count, 2); config_delete(cfg); } /* Test parse_args with --help returns 1 (clean exit) */ static void test_parse_args_help() { Config* cfg = config_create(); char* argv[] = {"fastsync", "--help"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 2, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, 1); config_delete(cfg); } /* Test parse_args with -V/--version returns 1 */ static void test_parse_args_version() { Config* cfg = config_create(); char* argv_short[] = {"fastsync", "-V"}; char* argv_long[] = {"fastsync", "--version"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 2, argv_short, positional_args, &positional_count); EXPECT_EQ_INT(ret, 1); ret = parse_args(cfg, 2, argv_long, positional_args, &positional_count); EXPECT_EQ_INT(ret, 1); config_delete(cfg); } /* Test parse_args with valid port */ static void test_parse_args_valid_port() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-p", "2222", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, 0); EXPECT_EQ_INT(cfg->ssh_port, 2222); EXPECT_EQ_INT(positional_count, 2); config_delete(cfg); } /* Test parse_args rejects port > 65535 */ static void test_parse_args_invalid_port() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-p", "99999", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, -1); config_delete(cfg); } /* Test parse_args rejects non-numeric port */ static void test_parse_args_non_numeric_port() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-p", "abc", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, -1); config_delete(cfg); } /* Test parse_args rejects server port > 65535 */ static void test_parse_args_invalid_server_port() { Config* cfg = config_create(); char* argv[] = {"fastsync", "--server-port", "70000", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, -1); config_delete(cfg); } /* Test parse_args rejects invalid compression level */ static void test_parse_args_invalid_compression_level() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-c", "25", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, -1); config_delete(cfg); } /* Test parse_args accepts valid compression level */ static void test_parse_args_valid_compression_level() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-c", "10", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 5, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, 0); EXPECT_EQ_INT(cfg->compression_level, 10); config_delete(cfg); } /* Test parse_args unknown option returns error */ static void test_parse_args_unknown_option() { Config* cfg = config_create(); char* argv[] = {"fastsync", "--nonexistent", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 4, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, -1); config_delete(cfg); } /* Test parse_args with --archive flag */ static void test_parse_args_archive() { Config* cfg = config_create(); char* argv[] = {"fastsync", "--archive", "/src", "/dst"}; int positional_args[2]; int positional_count = 0; int ret = parse_args(cfg, 4, argv, positional_args, &positional_count); EXPECT_EQ_INT(ret, 0); EXPECT_TRUE(cfg->use_compression); EXPECT_TRUE(cfg->use_multithreading); EXPECT_TRUE(cfg->use_metadata); config_delete(cfg); } void test_client_cli() { test_cli_help(); test_cli_archive_flags(); test_cli_dry_run(); test_cli_delete_flag(); test_cli_exclude_patterns(); test_parse_args_help(); test_parse_args_version(); test_parse_args_valid_port(); test_parse_args_invalid_port(); test_parse_args_non_numeric_port(); test_parse_args_invalid_server_port(); test_parse_args_invalid_compression_level(); test_parse_args_valid_compression_level(); test_parse_args_unknown_option(); test_parse_args_archive(); }