From: Alberto Leiva Popper Date: Tue, 3 Sep 2024 20:25:41 +0000 (-0600) Subject: Add more unit tests to the rsync timeout X-Git-Tag: 1.6.4~3^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a38a95ac42cbcf3387db6bbba308893ad55a1424;p=thirdparty%2FFORT-validator.git Add more unit tests to the rsync timeout Aight, think I'm done testing this. --- diff --git a/test/rsync/rsync_test.c b/test/rsync/rsync_test.c index 4e542531..5056ed89 100644 --- a/test/rsync/rsync_test.c +++ b/test/rsync/rsync_test.c @@ -1,17 +1,52 @@ #include #include "alloc.c" +#include "common.c" +#include "config/string_array.c" #include "mock.c" #include "rsync/rsync.c" -static char const * const PKT = "abcdefghijklmnopqrstuvwxyz"; -static const size_t PKTLEN = sizeof(PKT) - 1; +static char const STR64[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789 \n"; +static const size_t STR64LEN = sizeof(STR64) - 1; +static char content[1024]; +/* Mocks */ + +MOCK(config_get_rsync_program, char *, "rsync", void) +MOCK_UINT(config_get_rsync_retry_count, 0, void) +MOCK_UINT(config_get_rsync_retry_interval, 10, void) MOCK(config_get_rsync_transfer_timeout, long, 4, void) -__MOCK_ABORT(config_get_rsync_program, char *, NULL, void) -__MOCK_ABORT(config_get_rsync_args, struct string_array const *, NULL, void) -__MOCK_ABORT(config_get_rsync_retry_count, unsigned int, 0, void) -__MOCK_ABORT(config_get_rsync_retry_interval, unsigned int, 0, void) +__MOCK_ABORT(token_count, size_t, 0, struct string_tokenizer *t) +__MOCK_ABORT(token_read, char *, NULL, struct string_tokenizer *t) +MOCK_ABORT_VOID(string_tokenizer_init, struct string_tokenizer *t, + char const *s, size_t sl, unsigned char sp) +__MOCK_ABORT(string_tokenizer_next, bool, false, struct string_tokenizer *t) +MOCK_ABORT_INT(parse_json_string, json_t *json, char const *name, + char const **result) + +struct string_array const * +config_get_rsync_args(void) +{ + static char const *strs[] = { + /* Note, --bwlimit does not seem to exist in openrsync */ + "--bwlimit=1K", "-vvv", "$REMOTE", "$LOCAL" + }; + static struct string_array args; + if (args.length == 0) + string_array_init(&args, strs, ARRAY_LEN(strs)); + return &args; +} + +void +log_flush(void) +{ + fflush(stdout); + fflush(stderr); +} + +/* Tests */ static void disable_sigpipe(void) @@ -21,16 +56,35 @@ disable_sigpipe(void) pr_crit("Cannot disable SIGPIPE: %s", strerror(errno)); } +static void +init_content(void) +{ + size_t i; + + if (sizeof(content) % STR64LEN != 0) + pr_crit("content's length isn't divisible by str64's length"); + for (i = 0; i < (sizeof(content) / STR64LEN); i++) + memcpy(content + 64 * i, STR64, STR64LEN); +} + +static void +init_tmp(void) +{ + int res = mkdir("tmp/", 0700); + if (res && errno != EEXIST) + pr_crit("Could not create tmp/: %s", strerror(errno)); +} + static void * rsync_fast(void *arg) { int fds[2][2]; memcpy(fds, arg, sizeof(fds)); - ck_assert_int_eq(PKTLEN, write(STDERR_WRITE(fds), PKT, PKTLEN)); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); - ck_assert_int_eq(PKTLEN, write(STDERR_WRITE(fds), PKT, PKTLEN)); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDERR_WRITE(fds), STR64, STR64LEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); + ck_assert_int_eq(STR64LEN, write(STDERR_WRITE(fds), STR64, STR64LEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); close(STDERR_WRITE(fds)); close(STDOUT_WRITE(fds)); @@ -43,11 +97,11 @@ rsync_stalled(void *arg) int fds[2][2]; memcpy(fds, arg, sizeof(fds)); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); sleep(5); /* The timeout is 4 seconds */ - ck_assert_int_ne(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_ne(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); close(STDERR_WRITE(fds)); close(STDOUT_WRITE(fds)); @@ -60,16 +114,16 @@ rsync_drip_feed(void *arg) int fds[2][2]; memcpy(fds, arg, sizeof(fds)); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); sleep(1); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); - ck_assert_int_eq(PKTLEN, write(STDERR_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); + ck_assert_int_eq(STR64LEN, write(STDERR_WRITE(fds), STR64, STR64LEN)); sleep(1); - ck_assert_int_eq(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); sleep(1); - ck_assert_int_eq(PKTLEN, write(STDERR_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_eq(STR64LEN, write(STDERR_WRITE(fds), STR64, STR64LEN)); sleep(2); - ck_assert_int_ne(PKTLEN, write(STDOUT_WRITE(fds), PKT, PKTLEN)); + ck_assert_int_ne(STR64LEN, write(STDOUT_WRITE(fds), STR64, STR64LEN)); close(STDERR_WRITE(fds)); close(STDOUT_WRITE(fds)); @@ -77,7 +131,7 @@ rsync_drip_feed(void *arg) } static void -prepare_test(int fds[2][2], pthread_t *thread, void *(*rsync_simulator)(void *)) +prepare_exhaust(int fds[2][2], pthread_t *thread, void *(*rsync_simulator)(void *)) { ck_assert_int_eq(0, pipe(fds[0])); ck_assert_int_eq(0, pipe(fds[1])); @@ -85,32 +139,98 @@ prepare_test(int fds[2][2], pthread_t *thread, void *(*rsync_simulator)(void *)) } static void -finish_test(pthread_t thread) +finish_exhaust(pthread_t thread) { pthread_join(thread, NULL); } -START_TEST(read_pipe_test) /* Tests the read_pipe() function */ +START_TEST(exhaust_read_fds_test_normal) { int fds[2][2]; pthread_t rsync_writer; - printf("This test needs to exhaust some timeouts. Please be patient.\n"); - printf("Normal transfer\n"); - prepare_test(fds, &rsync_writer, rsync_fast); + prepare_exhaust(fds, &rsync_writer, rsync_fast); ck_assert_int_eq(0, exhaust_read_fds(STDERR_READ(fds), STDOUT_READ(fds))); - finish_test(rsync_writer); + finish_exhaust(rsync_writer); +} +END_TEST + +START_TEST(exhaust_read_fds_test_stalled) +{ + int fds[2][2]; + pthread_t rsync_writer; printf("Stalled transfer\n"); - prepare_test(fds, &rsync_writer, rsync_stalled); + prepare_exhaust(fds, &rsync_writer, rsync_stalled); ck_assert_int_eq(2, exhaust_read_fds(STDERR_READ(fds), STDOUT_READ(fds))); - finish_test(rsync_writer); + finish_exhaust(rsync_writer); +} +END_TEST + +START_TEST(exhaust_read_fds_test_drip) +{ + int fds[2][2]; + pthread_t rsync_writer; printf("Drip-feed\n"); - prepare_test(fds, &rsync_writer, rsync_drip_feed); + prepare_exhaust(fds, &rsync_writer, rsync_drip_feed); ck_assert_int_eq(2, exhaust_read_fds(STDERR_READ(fds), STDOUT_READ(fds))); - finish_test(rsync_writer); + finish_exhaust(rsync_writer); +} +END_TEST + +static void +create_file(char const *name, unsigned int kbs) +{ + FILE *file; + unsigned int k; + + file = fopen(name, "wb"); + ck_assert_ptr_ne(NULL, file); + for (k = 0; k < kbs; k++) + ck_assert_int_eq(sizeof(content), fwrite(content, 1, sizeof(content), file)); + ck_assert_int_eq(0, fclose(file)); +} + +static void +ensure_file_deleted(char const *name) +{ + int ret; + int error; + + errno = 0; + ret = unlink(name); + error = errno; + + ck_assert(ret == 0 || error == ENOENT); +} + +START_TEST(full_rsync_timeout_test_1kb) +{ + printf("1kb\n"); + create_file("tmp/1kb", 1); + ensure_file_deleted("tmp/1kb-copy"); + ck_assert_int_eq(0, rsync_download("tmp/1kb", "tmp/1kb-copy", false)); +} +END_TEST + +START_TEST(full_rsync_timeout_test_3kb) +{ + printf("3kb\n"); + create_file("tmp/3kb", 3); + ensure_file_deleted("tmp/3kb-copy"); + ck_assert_int_eq(0, rsync_download("tmp/3kb", "tmp/3kb-copy", false)); +} +END_TEST + +START_TEST(full_rsync_timeout_test_5kb) +{ + printf("5kb\n"); + create_file("tmp/5kb", 5); + ensure_file_deleted("tmp/5kb-copy"); + /* Max speed is 1kbps, timeout is 4 seconds */ + ck_assert_int_eq(EIO, rsync_download("tmp/5kb", "tmp/5kb-copy", false)); } END_TEST @@ -120,8 +240,13 @@ static Suite *xml_load_suite(void) TCase *pipes; pipes = tcase_create("pipes"); - tcase_add_test(pipes, read_pipe_test); - tcase_set_timeout(pipes, 15); + tcase_add_test(pipes, exhaust_read_fds_test_normal); + tcase_add_test(pipes, exhaust_read_fds_test_stalled); + tcase_add_test(pipes, exhaust_read_fds_test_drip); + tcase_add_test(pipes, full_rsync_timeout_test_1kb); + tcase_add_test(pipes, full_rsync_timeout_test_3kb); + tcase_add_test(pipes, full_rsync_timeout_test_5kb); + tcase_set_timeout(pipes, 6); suite = suite_create("rsync"); suite_add_tcase(suite, pipes); @@ -135,7 +260,10 @@ int main(void) SRunner *runner; int tests_failed; + printf("This test needs to exhaust some timeouts. Please be patient.\n"); disable_sigpipe(); + init_content(); + init_tmp(); suite = xml_load_suite();