]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/test/test-fileio.c
tree-wide: use -EBADF for fd initialization
[thirdparty/systemd.git] / src / test / test-fileio.c
index 321b544448d7812e92e863d88a05db7fecc8b086..2009c0f972b9faf7614b7514cf39e9e08c77ab61 100644 (file)
@@ -24,9 +24,8 @@
 #include "strv.h"
 #include "tests.h"
 #include "tmpfile-util.h"
-#include "util.h"
 
-static void test_parse_env_file(void) {
+TEST(parse_env_file) {
         _cleanup_(unlink_tempfilep) char
                 t[] = "/tmp/test-fileio-in-XXXXXX",
                 p[] = "/tmp/test-fileio-out-XXXXXX";
@@ -35,7 +34,6 @@ static void test_parse_env_file(void) {
                         *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL,
                         *eleven = NULL, *twelve = NULL, *thirteen = NULL;
         _cleanup_strv_free_ char **a = NULL, **b = NULL;
-        char **i;
         unsigned k;
         int r;
 
@@ -110,8 +108,7 @@ static void test_parse_env_file(void) {
                        "eleven", &eleven,
                        "twelve", &twelve,
                        "thirteen", &thirteen);
-
-        assert_se(r >= 0);
+        assert_se(r == 0);
 
         log_info("one=[%s]", strna(one));
         log_info("two=[%s]", strna(two));
@@ -166,13 +163,12 @@ static void test_one_shell_var(const char *file, const char *variable, const cha
         assert_se(streq(from_shell, value));
 }
 
-static void test_parse_multiline_env_file(void) {
+TEST(parse_multiline_env_file) {
         _cleanup_(unlink_tempfilep) char
                 t[] = "/tmp/test-fileio-in-XXXXXX",
                 p[] = "/tmp/test-fileio-out-XXXXXX";
         FILE *f;
         _cleanup_strv_free_ char **a = NULL, **b = NULL;
-        char **i;
         int r;
 
         assert_se(fmkostemp_safe(t, "w", &f) == 0);
@@ -218,11 +214,10 @@ static void test_parse_multiline_env_file(void) {
         assert_se(r >= 0);
 }
 
-static void test_merge_env_file(void) {
+TEST(merge_env_file) {
         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_strv_free_ char **a = NULL;
-        char **i;
         int r;
 
         assert_se(fmkostemp_safe(t, "w", &f) == 0);
@@ -241,7 +236,7 @@ static void test_merge_env_file(void) {
                                 "zzzz=${foobar:-${nothing}}\n"
                                 "zzzzz=${nothing:+${nothing}}\n"
                                 , WRITE_STRING_FILE_AVOID_NEWLINE);
-        assert(r >= 0);
+        assert_se(r >= 0);
 
         r = merge_env_file(&a, NULL, t);
         assert_se(r >= 0);
@@ -282,11 +277,10 @@ static void test_merge_env_file(void) {
         assert_se(a[10] == NULL);
 }
 
-static void test_merge_env_file_invalid(void) {
+TEST(merge_env_file_invalid) {
         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_strv_free_ char **a = NULL;
-        char **i;
         int r;
 
         assert_se(fmkostemp_safe(t, "w", &f) == 0);
@@ -305,7 +299,7 @@ static void test_merge_env_file_invalid(void) {
                                 "#\n"
                                 "\n\n"                  /* empty line */
                                 , WRITE_STRING_FILE_AVOID_NEWLINE);
-        assert(r >= 0);
+        assert_se(r >= 0);
 
         r = merge_env_file(&a, NULL, t);
         assert_se(r >= 0);
@@ -316,14 +310,12 @@ static void test_merge_env_file_invalid(void) {
         assert_se(strv_isempty(a));
 }
 
-static void test_executable_is_script(void) {
+TEST(executable_is_script) {
         _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         char *command;
         int r;
 
-        log_info("/* %s */", __func__);
-
         assert_se(fmkostemp_safe(t, "w", &f) == 0);
         fputs("#! /bin/script -a -b \ngoo goo", f);
         fflush(f);
@@ -344,13 +336,11 @@ static void test_executable_is_script(void) {
         }
 }
 
-static void test_status_field(void) {
+TEST(status_field) {
         _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
         unsigned long long total = 0, buffers = 0;
         int r;
 
-        log_info("/* %s */", __func__);
-
         assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
         puts(t);
         assert_se(streq(t, "1"));
@@ -381,9 +371,7 @@ static void test_status_field(void) {
         }
 }
 
-static void test_capeff(void) {
-        log_info("/* %s */", __func__);
-
+TEST(capeff) {
         for (int pid = 0; pid < 2; pid++) {
                 _cleanup_free_ char *capeff = NULL;
                 int r, p;
@@ -401,14 +389,12 @@ static void test_capeff(void) {
         }
 }
 
-static void test_write_string_stream(void) {
+TEST(write_string_stream) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         int fd;
         char buf[64];
 
-        log_info("/* %s */", __func__);
-
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
 
@@ -438,13 +424,11 @@ static void test_write_string_stream(void) {
         assert_se(streq(buf, "boohoo"));
 }
 
-static void test_write_string_file(void) {
+TEST(write_string_file) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
         char buf[64] = {};
         _cleanup_close_ int fd;
 
-        log_info("/* %s */", __func__);
-
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
 
@@ -454,13 +438,11 @@ static void test_write_string_file(void) {
         assert_se(streq(buf, "boohoo\n"));
 }
 
-static void test_write_string_file_no_create(void) {
+TEST(write_string_file_no_create) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
         _cleanup_close_ int fd;
         char buf[64] = {};
 
-        log_info("/* %s */", __func__);
-
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
 
@@ -471,12 +453,10 @@ static void test_write_string_file_no_create(void) {
         assert_se(streq(buf, "boohoo\n"));
 }
 
-static void test_write_string_file_verify(void) {
+TEST(write_string_file_verify) {
         _cleanup_free_ char *buf = NULL, *buf2 = NULL;
         int r;
 
-        log_info("/* %s */", __func__);
-
         r = read_one_line_file("/proc/version", &buf);
         if (ERRNO_IS_PRIVILEGE(r))
                 return;
@@ -496,14 +476,11 @@ static void test_write_string_file_verify(void) {
         assert_se(write_string_file("/proc/version", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
 }
 
-static void test_load_env_file_pairs(void) {
+TEST(load_env_file_pairs) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
         int fd, r;
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_strv_free_ char **l = NULL;
-        char **k, **v;
-
-        log_info("/* %s */", __func__);
 
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
@@ -539,7 +516,7 @@ static void test_load_env_file_pairs(void) {
         }
 }
 
-static void test_search_and_fopen(void) {
+TEST(search_and_fopen) {
         static const char* const dirs[] = {
                 "/tmp/foo/bar",
                 "/tmp",
@@ -548,12 +525,10 @@ static void test_search_and_fopen(void) {
         char name[] = "/tmp/test-search_and_fopen.XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *p = NULL;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         const char *e;
         int r;
 
-        log_info("/* %s */", __func__);
-
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
         fd = safe_close(fd);
@@ -578,29 +553,27 @@ static void test_search_and_fopen(void) {
         f = safe_fclose(f);
         p = mfree(p);
 
-        r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, (const char**) dirs, &f, &p);
+        r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r == -ENOENT);
-        r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, (const char**) dirs, &f, &p);
+        r = search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r == -ENOENT);
 
         r = unlink(name);
         assert_se(r == 0);
 
-        r = search_and_fopen(basename(name), "r", NULL, (const char**) dirs, &f, &p);
+        r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r == -ENOENT);
 }
 
-static void test_search_and_fopen_nulstr(void) {
+TEST(search_and_fopen_nulstr) {
         static const char dirs[] =
                 "/tmp/foo/bar\0"
                 "/tmp\0";
 
-        log_info("/* %s */", __func__);
-
         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *p = NULL;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         const char *e;
         int r;
 
@@ -621,27 +594,25 @@ static void test_search_and_fopen_nulstr(void) {
         f = safe_fclose(f);
         p = mfree(p);
 
-        r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f, &p);
+        r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "re", NULL, dirs, &f, &p);
         assert_se(r == -ENOENT);
-        r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f, &p);
+        r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "re", NULL, dirs, &f, &p);
         assert_se(r == -ENOENT);
 
         r = unlink(name);
         assert_se(r == 0);
 
-        r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f, &p);
+        r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
         assert_se(r == -ENOENT);
 }
 
-static void test_writing_tmpfile(void) {
+TEST(writing_tmpfile) {
         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
         _cleanup_free_ char *contents = NULL;
         size_t size;
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         int r;
 
-        log_info("/* %s */", __func__);
-
         struct iovec iov[] = {
                 IOVEC_MAKE_STRING("abc\n"),
                 IOVEC_MAKE_STRING(ALPHANUMERICAL "\n"),
@@ -660,11 +631,9 @@ static void test_writing_tmpfile(void) {
         assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
 }
 
-static void test_tempfn(void) {
+TEST(tempfn) {
         char *ret = NULL, *p;
 
-        log_info("/* %s */", __func__);
-
         assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
         assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
         free(ret);
@@ -703,11 +672,11 @@ static const char chars[] =
 
 DISABLE_WARNING_TYPE_LIMITS;
 
-static void test_fgetc(void) {
+TEST(fgetc) {
         _cleanup_fclose_ FILE *f = NULL;
         char c;
 
-        assert_se(f = fmemopen_unlocked((void*) chars, sizeof(chars), "re"));
+        assert_se(f = fmemopen_unlocked((void*) chars, sizeof(chars), "r"));
 
         for (size_t i = 0; i < sizeof(chars); i++) {
                 assert_se(safe_fgetc(f, &c) == 1);
@@ -797,22 +766,18 @@ static void test_read_line_one_file(FILE *f) {
         assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
 }
 
-static void test_read_line(void) {
+TEST(read_line1) {
         _cleanup_fclose_ FILE *f = NULL;
 
-        log_info("/* %s */", __func__);
-
-        assert_se(f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re"));
+        assert_se(f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "r"));
         test_read_line_one_file(f);
 }
 
-static void test_read_line2(void) {
+TEST(read_line2) {
         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX";
         int fd;
         _cleanup_fclose_ FILE *f = NULL;
 
-        log_info("/* %s */", __func__);
-
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
         assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
@@ -823,13 +788,11 @@ static void test_read_line2(void) {
         test_read_line_one_file(f);
 }
 
-static void test_read_line3(void) {
+TEST(read_line3) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *line = NULL;
         int r;
 
-        log_info("/* %s */", __func__);
-
         f = fopen("/proc/uptime", "re");
         if (!f && IN_SET(errno, ENOENT, EPERM))
                 return;
@@ -844,7 +807,7 @@ static void test_read_line3(void) {
         assert_se(read_line(f, LINE_MAX, NULL) == 0);
 }
 
-static void test_read_line4(void) {
+TEST(read_line4) {
         static const struct {
                 size_t length;
                 const char *string;
@@ -878,7 +841,7 @@ static void test_read_line4(void) {
         }
 }
 
-static void test_read_nul_string(void) {
+TEST(read_nul_string) {
         static const char test[] = "string nr. 1\0"
                 "string nr. 2\n\0"
                 "\377empty string follows\0"
@@ -889,8 +852,6 @@ static void test_read_nul_string(void) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *s = NULL;
 
-        log_info("/* %s */", __func__);
-
         assert_se(f = fmemopen_unlocked((void*) test, sizeof(test)-1, "r"));
 
         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1"));
@@ -914,18 +875,16 @@ static void test_read_nul_string(void) {
         assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 0 && streq_ptr(s, ""));
 }
 
-static void test_read_full_file_socket(void) {
+TEST(read_full_file_socket) {
         _cleanup_(rm_rf_physical_and_freep) char *z = NULL;
         _cleanup_close_ int listener = -1;
         _cleanup_free_ char *data = NULL, *clientname = NULL;
         union sockaddr_union sa;
-        const char *j;
+        const char *j, *jj;
         size_t size;
         pid_t pid;
         int r;
 
-        log_info("/* %s */", __func__);
-
         listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
         assert_se(listener >= 0);
 
@@ -937,6 +896,11 @@ static void test_read_full_file_socket(void) {
         assert_se(bind(listener, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0);
         assert_se(listen(listener, 1) >= 0);
 
+        /* Make sure the socket doesn't fit into a struct sockaddr_un, but we can still access it */
+        jj = strjoina(z, "/a_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_path");
+        assert_se(strlen(jj) > sizeof_field(struct sockaddr_un, sun_path));
+        assert_se(rename(j, jj) >= 0);
+
         /* Bind the *client* socket to some randomized name, to verify that this works correctly. */
         assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
 
@@ -945,7 +909,7 @@ static void test_read_full_file_socket(void) {
         if (r == 0) {
                 union sockaddr_union peer = {};
                 socklen_t peerlen = sizeof(peer);
-                _cleanup_close_ int rfd = -1;
+                _cleanup_close_ int rfd = -EBADF;
                 /* child */
 
                 rfd = accept4(listener, NULL, 0, SOCK_CLOEXEC);
@@ -964,8 +928,8 @@ static void test_read_full_file_socket(void) {
                 _exit(EXIT_SUCCESS);
         }
 
-        assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
-        assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
+        assert_se(read_full_file_full(AT_FDCWD, jj, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
+        assert_se(read_full_file_full(AT_FDCWD, jj, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
         assert_se(size == strlen(TEST_STR));
         assert_se(streq(data, TEST_STR));
 
@@ -973,15 +937,13 @@ static void test_read_full_file_socket(void) {
 #undef TEST_STR
 }
 
-static void test_read_full_file_offset_size(void) {
+TEST(read_full_file_offset_size) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_(unlink_and_freep) char *fn = NULL;
         _cleanup_free_ char *rbuf = NULL;
         size_t rbuf_size;
         uint8_t buf[4711];
 
-        log_info("/* %s */", __func__);
-
         random_bytes(buf, sizeof(buf));
 
         assert_se(tempfn_random_child(NULL, NULL, &fn) >= 0);
@@ -999,6 +961,25 @@ static void test_read_full_file_offset_size(void) {
         assert_se(memcmp(buf, rbuf, rbuf_size) == 0);
         rbuf = mfree(rbuf);
 
+        assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, 128, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) == -E2BIG);
+        assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, sizeof(buf)-1, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) == -E2BIG);
+        assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, sizeof(buf), READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) >= 0);
+        assert_se(rbuf_size == sizeof(buf));
+        assert_se(memcmp(buf, rbuf, rbuf_size) == 0);
+        rbuf = mfree(rbuf);
+
+        assert_se(read_full_file_full(AT_FDCWD, fn, 47, 128, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) == -E2BIG);
+        assert_se(read_full_file_full(AT_FDCWD, fn, 47, sizeof(buf)-47-1, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) == -E2BIG);
+        assert_se(read_full_file_full(AT_FDCWD, fn, 47, sizeof(buf)-47, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) >= 0);
+        assert_se(rbuf_size == sizeof(buf)-47);
+        assert_se(memcmp(buf+47, rbuf, rbuf_size) == 0);
+        rbuf = mfree(rbuf);
+
+        assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, sizeof(buf)+1, READ_FULL_FILE_FAIL_WHEN_LARGER, NULL, &rbuf, &rbuf_size) >= 0);
+        assert_se(rbuf_size == sizeof(buf));
+        assert_se(memcmp(buf, rbuf, rbuf_size) == 0);
+        rbuf = mfree(rbuf);
+
         assert_se(read_full_file_full(AT_FDCWD, fn, 1234, SIZE_MAX, 0, NULL, &rbuf, &rbuf_size) >= 0);
         assert_se(rbuf_size == sizeof(buf) - 1234);
         assert_se(memcmp(buf + 1234, rbuf, rbuf_size) == 0);
@@ -1019,8 +1000,7 @@ static void test_read_full_file_offset_size(void) {
         rbuf = mfree(rbuf);
 }
 
-static void test_read_virtual_file(size_t max_size) {
-        const char *filename;
+static void test_read_virtual_file_one(size_t max_size) {
         int r;
 
         log_info("/* %s (max_size=%zu) */", __func__, max_size);
@@ -1028,7 +1008,11 @@ static void test_read_virtual_file(size_t max_size) {
         FOREACH_STRING(filename,
                        "/proc/1/cmdline",
                        "/etc/nsswitch.conf",
-                       "/sys/kernel/uevent_seqnum") {
+                       "/sys/kernel/uevent_seqnum",
+                       "/proc/kcore",
+                       "/proc/kallsyms",
+                       "/proc/self/exe",
+                       "/proc/self/pagemap") {
 
                 _cleanup_free_ char *buf = NULL;
                 size_t size = 0;
@@ -1036,46 +1020,24 @@ static void test_read_virtual_file(size_t max_size) {
                 r = read_virtual_file(filename, max_size, &buf, &size);
                 if (r < 0) {
                         log_info_errno(r, "read_virtual_file(\"%s\", %zu): %m", filename, max_size);
-                        assert_se(ERRNO_IS_PRIVILEGE(r) || r == -ENOENT);
+                        assert_se(ERRNO_IS_PRIVILEGE(r) || /* /proc/kcore is not accessible to unpriv */
+                                  IN_SET(r,
+                                         -ENOENT,  /* Some of the files might be absent */
+                                         -EINVAL,  /* too small reads from /proc/self/pagemap trigger EINVAL */
+                                         -EFBIG)); /* /proc/kcore and /proc/self/pagemap should be too large */
                 } else
                         log_info("read_virtual_file(\"%s\", %zu): %s (%zu bytes)", filename, max_size, r ? "non-truncated" : "truncated", size);
         }
 }
 
-int main(int argc, char *argv[]) {
-        test_setup_logging(LOG_DEBUG);
-
-        test_parse_env_file();
-        test_parse_multiline_env_file();
-        test_merge_env_file();
-        test_merge_env_file_invalid();
-        test_executable_is_script();
-        test_status_field();
-        test_capeff();
-        test_write_string_stream();
-        test_write_string_file();
-        test_write_string_file_no_create();
-        test_write_string_file_verify();
-        test_load_env_file_pairs();
-        test_search_and_fopen();
-        test_search_and_fopen_nulstr();
-        test_writing_tmpfile();
-        test_tempfn();
-        test_fgetc();
-        test_read_line();
-        test_read_line2();
-        test_read_line3();
-        test_read_line4();
-        test_read_nul_string();
-        test_read_full_file_socket();
-        test_read_full_file_offset_size();
-        test_read_virtual_file(0);
-        test_read_virtual_file(1);
-        test_read_virtual_file(2);
-        test_read_virtual_file(20);
-        test_read_virtual_file(4096);
-        test_read_virtual_file(4097);
-        test_read_virtual_file(SIZE_MAX);
-
-        return 0;
+TEST(test_read_virtual_file) {
+        test_read_virtual_file_one(0);
+        test_read_virtual_file_one(1);
+        test_read_virtual_file_one(2);
+        test_read_virtual_file_one(20);
+        test_read_virtual_file_one(4096);
+        test_read_virtual_file_one(4097);
+        test_read_virtual_file_one(SIZE_MAX);
 }
+
+DEFINE_TEST_MAIN(LOG_DEBUG);