]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add more unit tests to the rsync timeout
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 3 Sep 2024 20:25:41 +0000 (14:25 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 3 Sep 2024 20:25:41 +0000 (14:25 -0600)
Aight, think I'm done testing this.

test/rsync/rsync_test.c

index 4e5425313632a7d6d11edc9c7d1b3f88477fe69b..5056ed8939fc64e36bd88f57062b54bf044f91fa 100644 (file)
@@ -1,17 +1,52 @@
 #include <check.h>
 
 #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();