]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/test/test-fileio.c
ASSERT_STREQ for simple cases
[thirdparty/systemd.git] / src / test / test-fileio.c
index 2009c0f972b9faf7614b7514cf39e9e08c77ab61..474eacaf0468df1f25b3657c27cded178815ba5e 100644 (file)
@@ -13,7 +13,8 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
-#include "io-util.h"
+#include "iovec-util.h"
+#include "memfd-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
@@ -70,27 +71,27 @@ TEST(parse_env_file) {
         STRV_FOREACH(i, a)
                 log_info("Got: <%s>", *i);
 
-        assert_se(streq_ptr(a[0], "one=BAR"));
-        assert_se(streq_ptr(a[1], "two=bar"));
-        assert_se(streq_ptr(a[2], "three=333\nxxxx"));
-        assert_se(streq_ptr(a[3], "four=44\\\"44"));
-        assert_se(streq_ptr(a[4], "five=55\"55FIVEcinco"));
-        assert_se(streq_ptr(a[5], "six=seis sechs sis"));
-        assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
-        assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
-        assert_se(streq_ptr(a[8], "export nine=nineval"));
-        assert_se(streq_ptr(a[9], "ten="));
-        assert_se(streq_ptr(a[10], "eleven=value"));
-        assert_se(streq_ptr(a[11], "twelve=\\value"));
-        assert_se(streq_ptr(a[12], "thirteen=\\value"));
-        assert_se(a[13] == NULL);
+        ASSERT_STREQ(a[0], "one=BAR");
+        ASSERT_STREQ(a[1], "two=bar");
+        ASSERT_STREQ(a[2], "three=333\nxxxx");
+        ASSERT_STREQ(a[3], "four=44\\\"44");
+        ASSERT_STREQ(a[4], "five=55\"55FIVEcinco");
+        ASSERT_STREQ(a[5], "six=seis sechs sis");
+        ASSERT_STREQ(a[6], "seven=sevenval#nocomment");
+        ASSERT_STREQ(a[7], "eight=eightval #nocomment");
+        ASSERT_STREQ(a[8], "export nine=nineval");
+        ASSERT_STREQ(a[9], "ten=");
+        ASSERT_STREQ(a[10], "eleven=value");
+        ASSERT_STREQ(a[11], "twelve=\\value");
+        ASSERT_STREQ(a[12], "thirteen=\\value");
+        ASSERT_NULL(a[13]);
 
         strv_env_clean(a);
 
         k = 0;
         STRV_FOREACH(i, b) {
                 log_info("Got2: <%s>", *i);
-                assert_se(streq(*i, a[k++]));
+                ASSERT_STREQ(*i, a[k++]);
         }
 
         r = parse_env_file(
@@ -124,19 +125,19 @@ TEST(parse_env_file) {
         log_info("twelve=[%s]", strna(twelve));
         log_info("thirteen=[%s]", strna(thirteen));
 
-        assert_se(streq(one, "BAR"));
-        assert_se(streq(two, "bar"));
-        assert_se(streq(three, "333\nxxxx"));
-        assert_se(streq(four, "44\\\"44"));
-        assert_se(streq(five, "55\"55FIVEcinco"));
-        assert_se(streq(six, "seis sechs sis"));
-        assert_se(streq(seven, "sevenval#nocomment"));
-        assert_se(streq(eight, "eightval #nocomment"));
-        assert_se(streq(nine, "nineval"));
-        assert_se(ten == NULL);
-        assert_se(streq(eleven, "value"));
-        assert_se(streq(twelve, "\\value"));
-        assert_se(streq(thirteen, "\\value"));
+        ASSERT_STREQ(one, "BAR");
+        ASSERT_STREQ(two, "bar");
+        ASSERT_STREQ(three, "333\nxxxx");
+        ASSERT_STREQ(four, "44\\\"44");
+        ASSERT_STREQ(five, "55\"55FIVEcinco");
+        ASSERT_STREQ(six, "seis sechs sis");
+        ASSERT_STREQ(seven, "sevenval#nocomment");
+        ASSERT_STREQ(eight, "eightval #nocomment");
+        ASSERT_STREQ(nine, "nineval");
+        ASSERT_NULL(ten);
+        ASSERT_STREQ(eleven, "value");
+        ASSERT_STREQ(twelve, "\\value");
+        ASSERT_STREQ(thirteen, "\\value");
 
         {
                 /* prepare a temporary file to write the environment to */
@@ -144,7 +145,7 @@ TEST(parse_env_file) {
                 assert_se(fd >= 0);
         }
 
-        r = write_env_file(p, a);
+        r = write_env_file(AT_FDCWD, p, NULL, a);
         assert_se(r >= 0);
 
         r = load_env_file(NULL, p, &b);
@@ -160,7 +161,7 @@ static void test_one_shell_var(const char *file, const char *variable, const cha
         assert_se(f = popen(cmd, "re"));
         assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
         assert_se(sz == strlen(value));
-        assert_se(streq(from_shell, value));
+        ASSERT_STREQ(from_shell, value);
 }
 
 TEST(parse_multiline_env_file) {
@@ -197,17 +198,17 @@ TEST(parse_multiline_env_file) {
         STRV_FOREACH(i, a)
                 log_info("Got: <%s>", *i);
 
-        assert_se(streq_ptr(a[0], "one=BAR    VAR\tGAR"));
-        assert_se(streq_ptr(a[1], "two=bar    var\tgar"));
-        assert_se(streq_ptr(a[2], "tri=bar     var \tgar "));
-        assert_se(a[3] == NULL);
+        ASSERT_STREQ(a[0], "one=BAR    VAR\tGAR");
+        ASSERT_STREQ(a[1], "two=bar    var\tgar");
+        ASSERT_STREQ(a[2], "tri=bar     var \tgar ");
+        ASSERT_NULL(a[3]);
 
         {
                 _cleanup_close_ int fd = mkostemp_safe(p);
                 assert_se(fd >= 0);
         }
 
-        r = write_env_file(p, a);
+        r = write_env_file(AT_FDCWD, p, NULL, a);
         assert_se(r >= 0);
 
         r = load_env_file(NULL, p, &b);
@@ -245,17 +246,17 @@ TEST(merge_env_file) {
         STRV_FOREACH(i, a)
                 log_info("Got: <%s>", *i);
 
-        assert_se(streq(a[0], "one=2"));
-        assert_se(streq(a[1], "twelve=12"));
-        assert_se(streq(a[2], "twentyone=21"));
-        assert_se(streq(a[3], "twentytwo=22"));
-        assert_se(streq(a[4], "xxx=0x222"));
-        assert_se(streq(a[5], "xxx_minus_three= - 3"));
-        assert_se(streq(a[6], "yyy=2"));
-        assert_se(streq(a[7], "zzz=replacement"));
-        assert_se(streq(a[8], "zzzz="));
-        assert_se(streq(a[9], "zzzzz="));
-        assert_se(a[10] == NULL);
+        ASSERT_STREQ(a[0], "one=2");
+        ASSERT_STREQ(a[1], "twelve=12");
+        ASSERT_STREQ(a[2], "twentyone=21");
+        ASSERT_STREQ(a[3], "twentytwo=22");
+        ASSERT_STREQ(a[4], "xxx=0x222");
+        ASSERT_STREQ(a[5], "xxx_minus_three= - 3");
+        ASSERT_STREQ(a[6], "yyy=2");
+        ASSERT_STREQ(a[7], "zzz=replacement");
+        ASSERT_STREQ(a[8], "zzzz=");
+        ASSERT_STREQ(a[9], "zzzzz=");
+        ASSERT_NULL(a[10]);
 
         r = merge_env_file(&a, NULL, t);
         assert_se(r >= 0);
@@ -264,17 +265,17 @@ TEST(merge_env_file) {
         STRV_FOREACH(i, a)
                 log_info("Got2: <%s>", *i);
 
-        assert_se(streq(a[0], "one=2"));
-        assert_se(streq(a[1], "twelve=12"));
-        assert_se(streq(a[2], "twentyone=21"));
-        assert_se(streq(a[3], "twentytwo=22"));
-        assert_se(streq(a[4], "xxx=0x222"));
-        assert_se(streq(a[5], "xxx_minus_three=0x222 - 3"));
-        assert_se(streq(a[6], "yyy=2"));
-        assert_se(streq(a[7], "zzz=replacement"));
-        assert_se(streq(a[8], "zzzz="));
-        assert_se(streq(a[9], "zzzzz="));
-        assert_se(a[10] == NULL);
+        ASSERT_STREQ(a[0], "one=2");
+        ASSERT_STREQ(a[1], "twelve=12");
+        ASSERT_STREQ(a[2], "twentyone=21");
+        ASSERT_STREQ(a[3], "twentytwo=22");
+        ASSERT_STREQ(a[4], "xxx=0x222");
+        ASSERT_STREQ(a[5], "xxx_minus_three=0x222 - 3");
+        ASSERT_STREQ(a[6], "yyy=2");
+        ASSERT_STREQ(a[7], "zzz=replacement");
+        ASSERT_STREQ(a[8], "zzzz=");
+        ASSERT_STREQ(a[9], "zzzzz=");
+        ASSERT_NULL(a[10]);
 }
 
 TEST(merge_env_file_invalid) {
@@ -322,14 +323,13 @@ TEST(executable_is_script) {
 
         r = executable_is_script(t, &command);
         assert_se(r > 0);
-        assert_se(streq(command, "/bin/script"));
+        ASSERT_STREQ(command, "/bin/script");
         free(command);
 
         r = executable_is_script("/bin/sh", &command);
         assert_se(r == 0);
 
         r = executable_is_script("/usr/bin/yum", &command);
-        assert_se(r > 0 || r == -ENOENT);
         if (r > 0) {
                 assert_se(startswith(command, "/"));
                 free(command);
@@ -337,14 +337,10 @@ TEST(executable_is_script) {
 }
 
 TEST(status_field) {
-        _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
+        _cleanup_free_ char *p = NULL, *s = NULL, *z = NULL;
         unsigned long long total = 0, buffers = 0;
         int r;
 
-        assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
-        puts(t);
-        assert_se(streq(t, "1"));
-
         r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
         if (r != -ENOENT) {
                 assert_se(r == 0);
@@ -389,6 +385,42 @@ TEST(capeff) {
         }
 }
 
+TEST(read_one_line_file) {
+        _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-fileio-1lf-XXXXXX";
+        int fd;
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *buf, *buf2, *buf3, *buf4, *buf5;
+
+        fd = mkostemp_safe(fn);
+        assert_se(fd >= 0);
+
+        f = fdopen(fd, "we");
+        assert_se(f);
+
+        assert_se(read_one_line_file(fn, &buf) == 0);
+        ASSERT_STREQ(buf, "");
+        assert_se(read_one_line_file(fn, &buf2) == 0);
+        ASSERT_STREQ(buf2, "");
+
+        assert_se(write_string_stream(f, "x", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+        fflush(f);
+
+        assert_se(read_one_line_file(fn, &buf3) == 1);
+        ASSERT_STREQ(buf3, "x");
+
+        assert_se(write_string_stream(f, "\n", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+        fflush(f);
+
+        assert_se(read_one_line_file(fn, &buf4) == 2);
+        ASSERT_STREQ(buf4, "x");
+
+        assert_se(write_string_stream(f, "\n", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+        fflush(f);
+
+        assert_se(read_one_line_file(fn, &buf5) == 2);
+        ASSERT_STREQ(buf5, "x");
+}
+
 TEST(write_string_stream) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
         _cleanup_fclose_ FILE *f = NULL;
@@ -410,7 +442,7 @@ TEST(write_string_stream) {
         rewind(f);
 
         assert_se(fgets(buf, sizeof(buf), f));
-        assert_se(streq(buf, "boohoo\n"));
+        ASSERT_STREQ(buf, "boohoo\n");
         f = safe_fclose(f);
 
         f = fopen(fn, "w+");
@@ -421,13 +453,13 @@ TEST(write_string_stream) {
 
         assert_se(fgets(buf, sizeof(buf), f));
         printf(">%s<", buf);
-        assert_se(streq(buf, "boohoo"));
+        ASSERT_STREQ(buf, "boohoo");
 }
 
 TEST(write_string_file) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
         char buf[64] = {};
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
@@ -435,12 +467,12 @@ TEST(write_string_file) {
         assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
 
         assert_se(read(fd, buf, sizeof(buf)) == 7);
-        assert_se(streq(buf, "boohoo\n"));
+        ASSERT_STREQ(buf, "boohoo\n");
 }
 
 TEST(write_string_file_no_create) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -EBADF;
         char buf[64] = {};
 
         fd = mkostemp_safe(fn);
@@ -450,7 +482,7 @@ TEST(write_string_file_no_create) {
         assert_se(write_string_file(fn, "boohoo", 0) == 0);
 
         assert_se(read(fd, buf, sizeof buf) == (ssize_t) strlen("boohoo\n"));
-        assert_se(streq(buf, "boohoo\n"));
+        ASSERT_STREQ(buf, "boohoo\n");
 }
 
 TEST(write_string_file_verify) {
@@ -458,7 +490,7 @@ TEST(write_string_file_verify) {
         int r;
 
         r = read_one_line_file("/proc/version", &buf);
-        if (ERRNO_IS_PRIVILEGE(r))
+        if (ERRNO_IS_NEG_PRIVILEGE(r))
                 return;
         assert_se(r >= 0);
         assert_se(buf2 = strjoin(buf, "\n"));
@@ -476,6 +508,23 @@ TEST(write_string_file_verify) {
         assert_se(write_string_file("/proc/version", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
 }
 
+static void check_file_pairs_one(char **l) {
+        assert_se(l);
+        assert_se(strv_length(l) == 14);
+
+        STRV_FOREACH_PAIR(k, v, l) {
+                assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
+                printf("%s=%s\n", *k, *v);
+                assert_se(!streq(*k, "NAME") || streq(*v, "Arch Linux"));
+                assert_se(!streq(*k, "ID") || streq(*v, "arch"));
+                assert_se(!streq(*k, "PRETTY_NAME") || streq(*v, "Arch Linux"));
+                assert_se(!streq(*k, "ANSI_COLOR") || streq(*v, "0;36"));
+                assert_se(!streq(*k, "HOME_URL") || streq(*v, "https://www.archlinux.org/"));
+                assert_se(!streq(*k, "SUPPORT_URL") || streq(*v, "https://bbs.archlinux.org/"));
+                assert_se(!streq(*k, "BUG_REPORT_URL") || streq(*v, "https://bugs.archlinux.org/"));
+        }
+}
+
 TEST(load_env_file_pairs) {
         _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
         int fd, r;
@@ -496,24 +545,17 @@ TEST(load_env_file_pairs) {
                         WRITE_STRING_FILE_CREATE);
         assert_se(r == 0);
 
+        r = load_env_file_pairs_fd(fd, fn, &l);
+        assert_se(r >= 0);
+        check_file_pairs_one(l);
+        l = strv_free(l);
+
         f = fdopen(fd, "r");
         assert_se(f);
 
         r = load_env_file_pairs(f, fn, &l);
         assert_se(r >= 0);
-
-        assert_se(strv_length(l) == 14);
-        STRV_FOREACH_PAIR(k, v, l) {
-                assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
-                printf("%s=%s\n", *k, *v);
-                if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
-                if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
-                if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
-                if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
-                if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
-                if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
-                if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
-        }
+        check_file_pairs_one(l);
 }
 
 TEST(search_and_fopen) {
@@ -536,33 +578,56 @@ TEST(search_and_fopen) {
         r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r >= 0);
         assert_se(e = path_startswith(p, "/tmp/"));
-        assert_se(streq(basename(name), e));
+        ASSERT_STREQ(basename(name), e);
         f = safe_fclose(f);
         p = mfree(p);
 
+        r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+        assert_se(r >= 0);
+        assert_se(e = path_startswith(p, "/tmp/"));
+        ASSERT_STREQ(basename(name), e);
+        p = mfree(p);
+
         r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r >= 0);
         assert_se(path_equal(name, p));
         f = safe_fclose(f);
         p = mfree(p);
 
+        r = search_and_fopen(name, NULL, NULL, (const char**) dirs, NULL, &p);
+        assert_se(r >= 0);
+        assert_se(path_equal(name, p));
+        p = mfree(p);
+
         r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
         assert_se(r >= 0);
         assert_se(e = path_startswith(p, "/tmp/"));
-        assert_se(streq(basename(name), e));
+        ASSERT_STREQ(basename(name), e);
         f = safe_fclose(f);
         p = mfree(p);
 
+        r = search_and_fopen(basename(name), NULL, "/", (const char**) dirs, NULL, &p);
+        assert_se(r >= 0);
+        assert_se(e = path_startswith(p, "/tmp/"));
+        ASSERT_STREQ(basename(name), e);
+        p = mfree(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("/a/file/which/does/not/exist/i/guess", NULL, NULL, (const char**) dirs, NULL, &p);
+        assert_se(r == -ENOENT);
         r = search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r == -ENOENT);
+        r = search_and_fopen("afilewhichdoesnotexistiguess", NULL, NULL, (const char**) dirs, NULL, &p);
+        assert_se(r == -ENOENT);
 
         r = unlink(name);
         assert_se(r == 0);
 
         r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r == -ENOENT);
+        r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+        assert_se(r == -ENOENT);
 }
 
 TEST(search_and_fopen_nulstr) {
@@ -584,7 +649,7 @@ TEST(search_and_fopen_nulstr) {
         r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
         assert_se(r >= 0);
         assert_se(e = path_startswith(p, "/tmp/"));
-        assert_se(streq(basename(name), e));
+        ASSERT_STREQ(basename(name), e);
         f = safe_fclose(f);
         p = mfree(p);
 
@@ -628,18 +693,18 @@ TEST(writing_tmpfile) {
         r = read_full_file(name, &contents, &size);
         assert_se(r == 0);
         printf("contents: %s", contents);
-        assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+        ASSERT_STREQ(contents, "abc\n" ALPHANUMERICAL "\n");
 }
 
 TEST(tempfn) {
         char *ret = NULL, *p;
 
         assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
-        assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+        ASSERT_STREQ(ret, "/foo/bar/.#waldoXXXXXX");
         free(ret);
 
         assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
-        assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+        ASSERT_STREQ(ret, "/foo/bar/.#[miau]waldoXXXXXX");
         free(ret);
 
         assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
@@ -835,7 +900,7 @@ TEST(read_line4) {
 
                 r = read_line(f, SIZE_MAX, &s);
                 assert_se((size_t) r == eof_endings[i].length);
-                assert_se(streq_ptr(s, "foo"));
+                ASSERT_STREQ(s, "foo");
 
                 assert_se(read_line(f, SIZE_MAX, NULL) == 0); /* Ensure we hit EOF */
         }
@@ -877,7 +942,7 @@ TEST(read_nul_string) {
 
 TEST(read_full_file_socket) {
         _cleanup_(rm_rf_physical_and_freep) char *z = NULL;
-        _cleanup_close_ int listener = -1;
+        _cleanup_close_ int listener = -EBADF;
         _cleanup_free_ char *data = NULL, *clientname = NULL;
         union sockaddr_union sa;
         const char *j, *jj;
@@ -904,7 +969,7 @@ TEST(read_full_file_socket) {
         /* Bind the *client* socket to some randomized name, to verify that this works correctly. */
         assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
 
-        r = safe_fork("(server)", FORK_DEATHSIG|FORK_LOG, &pid);
+        r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
         assert_se(r >= 0);
         if (r == 0) {
                 union sockaddr_union peer = {};
@@ -920,7 +985,7 @@ TEST(read_full_file_socket) {
                 assert_se(peer.un.sun_family == AF_UNIX);
                 assert_se(peerlen > offsetof(struct sockaddr_un, sun_path));
                 assert_se(peer.un.sun_path[0] == 0);
-                assert_se(streq(peer.un.sun_path + 1, clientname + 1));
+                ASSERT_STREQ(peer.un.sun_path + 1, clientname + 1);
 
 #define TEST_STR "This is a test\nreally."
 
@@ -931,7 +996,7 @@ TEST(read_full_file_socket) {
         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));
+        ASSERT_STREQ(data, TEST_STR);
 
         assert_se(wait_for_terminate_and_check("(server)", pid, WAIT_LOG) >= 0);
 #undef TEST_STR
@@ -1024,13 +1089,14 @@ static void test_read_virtual_file_one(size_t max_size) {
                                   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 */
+                                         -EFBIG,   /* /proc/kcore and /proc/self/pagemap should be too large */
+                                         -EBADF)); /* /proc/kcore is masked when we are running in docker. */
                 } else
                         log_info("read_virtual_file(\"%s\", %zu): %s (%zu bytes)", filename, max_size, r ? "non-truncated" : "truncated", size);
         }
 }
 
-TEST(test_read_virtual_file) {
+TEST(read_virtual_file) {
         test_read_virtual_file_one(0);
         test_read_virtual_file_one(1);
         test_read_virtual_file_one(2);
@@ -1040,4 +1106,46 @@ TEST(test_read_virtual_file) {
         test_read_virtual_file_one(SIZE_MAX);
 }
 
+TEST(fdopen_independent) {
+#define TEST_TEXT "this is some random test text we are going to write to a memfd"
+        _cleanup_close_ int fd = -EBADF;
+        _cleanup_fclose_ FILE *f = NULL;
+        char buf[STRLEN(TEST_TEXT) + 1];
+
+        fd = memfd_new("fdopen_independent");
+        if (fd < 0) {
+                assert_se(ERRNO_IS_NOT_SUPPORTED(fd));
+                return;
+        }
+
+        assert_se(write(fd, TEST_TEXT, strlen(TEST_TEXT)) == strlen(TEST_TEXT));
+        /* we'll leave the read offset at the end of the memfd, the fdopen_independent() descriptors should
+         * start at the beginning anyway */
+
+        assert_se(fdopen_independent(fd, "re", &f) >= 0);
+        zero(buf);
+        assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+        ASSERT_STREQ(buf, TEST_TEXT);
+        assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
+        assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+        f = safe_fclose(f);
+
+        assert_se(fdopen_independent(fd, "r", &f) >= 0);
+        zero(buf);
+        assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+        ASSERT_STREQ(buf, TEST_TEXT);
+        assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
+        assert_se(!FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+        f = safe_fclose(f);
+
+        assert_se(fdopen_independent(fd, "r+e", &f) >= 0);
+        zero(buf);
+        assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+        ASSERT_STREQ(buf, TEST_TEXT);
+        assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDWR);
+        assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+        f = safe_fclose(f);
+}
+
+
 DEFINE_TEST_MAIN(LOG_DEBUG);