From d8351049a8547be4a512d29d9b4127ff1920b6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 23 Oct 2018 10:50:09 +0200 Subject: [PATCH 1/5] Introduce fmkostemp_safe and use it in tests No functional change. --- src/basic/fileio.c | 18 ++++++++++ src/basic/fileio.h | 1 + src/shared/serialize.c | 2 +- src/test/test-clock.c | 9 ++--- src/test/test-conf-parser.c | 11 +++--- src/test/test-env-util.c | 11 ++---- src/test/test-fileio.c | 64 ++++++++++++----------------------- src/test/test-terminal-util.c | 8 ++--- 8 files changed, 53 insertions(+), 71 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index d2fd4c47b3..f14afa5dce 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1221,6 +1221,24 @@ int mkostemp_safe(char *pattern) { return fd; } +int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) { + int fd; + FILE *f; + + fd = mkostemp_safe(pattern); + if (fd < 0) + return fd; + + f = fdopen(fd, mode); + if (!f) { + safe_close(fd); + return -errno; + } + + *ret_f = f; + return 0; +} + int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { const char *fn; char *t; diff --git a/src/basic/fileio.h b/src/basic/fileio.h index e84710f138..102d33d75f 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -64,6 +64,7 @@ int fflush_sync_and_check(FILE *f); int fopen_temporary(const char *path, FILE **_f, char **_temp_path); int mkostemp_safe(char *pattern); +int fmkostemp_safe(char *pattern, const char *mode, FILE**_f); int tempfn_xxxxxx(const char *p, const char *extra, char **ret); int tempfn_random(const char *p, const char *extra, char **ret); diff --git a/src/shared/serialize.c b/src/shared/serialize.c index c76a0d0d9e..3a6f8f60eb 100644 --- a/src/shared/serialize.c +++ b/src/shared/serialize.c @@ -113,7 +113,7 @@ int serialize_strv(FILE *f, const char *key, char **l) { int ret = 0, r; char **i; - /* Returns the first error */ + /* Returns the first error, or positive if anything was serialized, 0 otherwise. */ STRV_FOREACH(i, l) { r = serialize_item_escaped(f, key, *i); diff --git a/src/test/test-clock.c b/src/test/test-clock.c index 50e9b7756f..95ac8de91b 100644 --- a/src/test/test-clock.c +++ b/src/test/test-clock.c @@ -9,12 +9,12 @@ #include "clock-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "log.h" #include "macro.h" static void test_clock_is_localtime(void) { char adjtime[] = "/tmp/test-adjtime.XXXXXX"; - int fd = -1; _cleanup_fclose_ FILE* f = NULL; static const struct scenario { @@ -41,17 +41,14 @@ static void test_clock_is_localtime(void) { /* without an adjtime file we default to UTC */ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0); - fd = mkostemp_safe(adjtime); - assert_se(fd >= 0); + assert_se(fmkostemp_safe(adjtime, "w", &f) == 0); log_info("adjtime test file: %s", adjtime); - f = fdopen(fd, "w"); - assert_se(f); for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) { log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result); log_info("%s", scenarios[i].contents); rewind(f); - ftruncate(fd, 0); + ftruncate(fileno(f), 0); assert_se(write_string_stream(f, scenarios[i].contents, WRITE_STRING_FILE_AVOID_NEWLINE) == 0); assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result); } diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c index ff951d12f4..91f1d9a386 100644 --- a/src/test/test-conf-parser.c +++ b/src/test/test-conf-parser.c @@ -311,9 +311,9 @@ static const char* const config_file[] = { static void test_config_parse(unsigned i, const char *s) { _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX"; - int fd, r; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *setting1 = NULL; + int r; const ConfigTableItem items[] = { { "Section", "setting1", config_parse_string, 0, &setting1}, @@ -322,12 +322,9 @@ static void test_config_parse(unsigned i, const char *s) { log_info("== %s[%i] ==", __func__, i); - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se((size_t) write(fd, s, strlen(s)) == strlen(s)); - - assert_se(lseek(fd, 0, SEEK_SET) == 0); - assert_se(f = fdopen(fd, "r")); + assert_se(fmkostemp_safe(name, "r+", &f) == 0); + assert_se(fwrite(s, strlen(s), 1, f) == 1); + rewind(f); /* int config_parse(const char *unit, diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c index c988fc6eee..0ab671b476 100644 --- a/src/test/test-env-util.c +++ b/src/test/test-env-util.c @@ -323,8 +323,7 @@ static void test_serialize_environment(void) { _cleanup_strv_free_ char **env = NULL, **env2 = NULL; char fn[] = "/tmp/test-env-util.XXXXXXX"; _cleanup_fclose_ FILE *f = NULL; - int fd, r; - + int r; assert_se(env = strv_new("A=1", "B=2", @@ -333,12 +332,8 @@ static void test_serialize_environment(void) { "FOO%%=a\177b\nc\td e", NULL)); - fd = mkostemp_safe(fn); - assert_se(fd >= 0); - - assert_se(f = fdopen(fd, "r+")); - - assert_se(serialize_strv(f, "env", env) > 0); + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + assert_se(serialize_strv(f, "env", env) == 1); assert_se(fflush_and_check(f) == 0); rewind(f); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index aa38a7d29a..cabaef6ab8 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -23,24 +23,15 @@ static void test_parse_env_file(void) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-in-XXXXXX", p[] = "/tmp/test-fileio-out-XXXXXX"; - int fd, r; FILE *f; _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL, *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL; _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; unsigned k; + int r; - fd = mkostemp_safe(p); - assert_se(fd >= 0); - close(fd); - - fd = mkostemp_safe(t); - assert_se(fd >= 0); - - f = fdopen(fd, "w"); - assert_se(f); - + assert_se(fmkostemp_safe(t, "w", &f) == 0); fputs("one=BAR \n" "# comment\n" " # comment \n" @@ -128,6 +119,12 @@ static void test_parse_env_file(void) { assert_se(streq(nine, "nineval")); assert_se(ten == NULL); + { + /* prepare a temporary file to write the environment to */ + _cleanup_close_ int fd = mkostemp_safe(p); + assert_se(fd >= 0); + } + r = write_env_file(p, a); assert_se(r >= 0); @@ -139,21 +136,12 @@ static void test_parse_multiline_env_file(void) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-in-XXXXXX", p[] = "/tmp/test-fileio-out-XXXXXX"; - int fd, r; FILE *f; _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; + int r; - fd = mkostemp_safe(p); - assert_se(fd >= 0); - close(fd); - - fd = mkostemp_safe(t); - assert_se(fd >= 0); - - f = fdopen(fd, "w"); - assert_se(f); - + assert_se(fmkostemp_safe(t, "w", &f) == 0); fputs("one=BAR\\\n" " VAR\\\n" "\tGAR\n" @@ -180,6 +168,11 @@ static void test_parse_multiline_env_file(void) { assert_se(streq_ptr(a[2], "tri=bar var \tgar ")); assert_se(a[3] == NULL); + { + _cleanup_close_ int fd = mkostemp_safe(p); + assert_se(fd >= 0); + } + r = write_env_file(p, a); assert_se(r >= 0); @@ -189,19 +182,14 @@ static void test_parse_multiline_env_file(void) { static void test_merge_env_file(void) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; - int fd, r; _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **a = NULL; char **i; + int r; - fd = mkostemp_safe(t); - assert_se(fd >= 0); - + assert_se(fmkostemp_safe(t, "w", &f) == 0); log_info("/* %s (%s) */", __func__, t); - f = fdopen(fd, "w"); - assert_se(f); - r = write_string_stream(f, "one=1 \n" "twelve=${one}2\n" @@ -258,19 +246,14 @@ static void test_merge_env_file(void) { static void test_merge_env_file_invalid(void) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; - int fd, r; _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **a = NULL; char **i; + int r; - fd = mkostemp_safe(t); - assert_se(fd >= 0); - + assert_se(fmkostemp_safe(t, "w", &f) == 0); log_info("/* %s (%s) */", __func__, t); - f = fdopen(fd, "w"); - assert_se(f); - r = write_string_stream(f, "unset one \n" "unset one= \n" @@ -297,16 +280,11 @@ static void test_merge_env_file_invalid(void) { static void test_executable_is_script(void) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; - int fd, r; _cleanup_fclose_ FILE *f = NULL; char *command; + int r; - fd = mkostemp_safe(t); - assert_se(fd >= 0); - - f = fdopen(fd, "w"); - assert_se(f); - + assert_se(fmkostemp_safe(t, "w", &f) == 0); fputs("#! /bin/script -a -b \ngoo goo", f); fflush(f); diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index 9f27c74139..fbe8133b10 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -32,15 +32,11 @@ static void test_read_one_char(void) { char r; bool need_nl; char name[] = "/tmp/test-read_one_char.XXXXXX"; - int fd; - fd = mkostemp_safe(name); - assert_se(fd >= 0); - file = fdopen(fd, "r+"); - assert_se(file); + assert(fmkostemp_safe(name, "r+", &file) == 0); + assert_se(fputs("c\n", file) >= 0); rewind(file); - assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0); assert_se(!need_nl); assert_se(r == 'c'); From 75e7d50e261c42d3de9afc7ad7368308f45c1498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 23 Oct 2018 10:50:38 +0200 Subject: [PATCH 2/5] test: _cleanup_(unlink_tempfilep) in two more places --- src/test/test-clock.c | 4 +--- src/test/test-env-util.c | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/test-clock.c b/src/test/test-clock.c index 95ac8de91b..f5b9a72727 100644 --- a/src/test/test-clock.c +++ b/src/test/test-clock.c @@ -14,7 +14,7 @@ #include "macro.h" static void test_clock_is_localtime(void) { - char adjtime[] = "/tmp/test-adjtime.XXXXXX"; + _cleanup_(unlink_tempfilep) char adjtime[] = "/tmp/test-adjtime.XXXXXX"; _cleanup_fclose_ FILE* f = NULL; static const struct scenario { @@ -52,8 +52,6 @@ static void test_clock_is_localtime(void) { assert_se(write_string_stream(f, scenarios[i].contents, WRITE_STRING_FILE_AVOID_NEWLINE) == 0); assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result); } - - unlink(adjtime); } /* Test with the real /etc/adjtime */ diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c index 0ab671b476..815fb340af 100644 --- a/src/test/test-env-util.c +++ b/src/test/test-env-util.c @@ -6,6 +6,7 @@ #include "env-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "serialize.h" #include "string-util.h" #include "strv.h" @@ -321,7 +322,7 @@ static void test_deserialize_environment(void) { static void test_serialize_environment(void) { _cleanup_strv_free_ char **env = NULL, **env2 = NULL; - char fn[] = "/tmp/test-env-util.XXXXXXX"; + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX"; _cleanup_fclose_ FILE *f = NULL; int r; @@ -358,8 +359,6 @@ static void test_serialize_environment(void) { assert_se(feof(f)); assert_se(strv_equal(env, env2)); - - unlink(fn); } int main(int argc, char *argv[]) { From 40a4c4b38d543314d93c8d9adde1b167033d230d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 23 Oct 2018 12:00:31 +0200 Subject: [PATCH 3/5] test-serialize: a smoke test for the serialization functions --- src/test/meson.build | 4 + src/test/test-serialize.c | 149 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/test/test-serialize.c diff --git a/src/test/meson.build b/src/test/meson.build index cf060c3bd1..6c81131c99 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -143,6 +143,10 @@ tests += [ libmount, libblkid]], + [['src/test/test-serialize.c'], + [], + []], + [['src/test/test-utf8.c'], [], []], diff --git a/src/test/test-serialize.c b/src/test/test-serialize.c new file mode 100644 index 0000000000..5959455411 --- /dev/null +++ b/src/test/test-serialize.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "def.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "serialize.h" +#include "strv.h" +#include "tests.h" + +#define sixteen(x) x x x x x x x x x x x x x x x x +#define million(x) sixteen(sixteen(sixteen(sixteen(sixteen(x))))) + +#define long_string million("x") +assert_cc(STRLEN(long_string) == LONG_LINE_MAX); + +static void test_serialize_item(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_item(f, "a", NULL) == 0); + assert_se(serialize_item(f, "a", "bbb") == 1); + assert_se(serialize_item(f, "a", "bbb") == 1); + assert_se(serialize_item(f, "a", long_string) == -EINVAL); + assert_se(serialize_item(f, long_string, "a") == -EINVAL); + assert_se(serialize_item(f, long_string, long_string) == -EINVAL); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL; + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(streq(line2, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0); + assert_se(streq(line3, "")); +} + +static void test_serialize_item_escaped(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_item_escaped(f, "a", NULL) == 0); + assert_se(serialize_item_escaped(f, "a", "bbb") == 1); + assert_se(serialize_item_escaped(f, "a", "bbb") == 1); + assert_se(serialize_item_escaped(f, "a", long_string) == -EINVAL); + assert_se(serialize_item_escaped(f, long_string, "a") == -EINVAL); + assert_se(serialize_item_escaped(f, long_string, long_string) == -EINVAL); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL; + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(streq(line2, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0); + assert_se(streq(line3, "")); +} + +static void test_serialize_usec(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_usec(f, "usec1", USEC_INFINITY) == 0); + assert_se(serialize_usec(f, "usec2", 0) == 1); + assert_se(serialize_usec(f, "usec3", USEC_INFINITY-1) == 1); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL; + usec_t x; + + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "usec2=0")); + assert_se(deserialize_usec(line1 + 6, &x) == 0); + assert_se(x == 0); + + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(startswith(line2, "usec3=")); + assert_se(deserialize_usec(line2 + 6, &x) == 0); + assert_se(x == USEC_INFINITY-1); +} + +static void test_serialize_strv(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + char **strv = STRV_MAKE("a", "b", "foo foo", + "nasty1 \"", + "\"nasty2 ", + "nasty3 '", + "\"nasty4 \"", + "nasty5\n", + "\nnasty5\nfoo=bar", + "\nnasty5\nfoo=bar"); + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_strv(f, "strv1", NULL) == 0); + assert_se(serialize_strv(f, "strv2", STRV_MAKE_EMPTY) == 0); + assert_se(serialize_strv(f, "strv3", strv) == 1); + assert_se(serialize_strv(f, "strv4", STRV_MAKE(long_string)) == -EINVAL); + + rewind(f); + + _cleanup_strv_free_ char **strv2 = NULL; + for (;;) { + _cleanup_free_ char *line = NULL; + int r; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + break; + assert_se(r > 0); + + const char *t = startswith(line, "strv3="); + assert_se(t); + + char *un; + assert_se(cunescape(t, 0, &un) >= 0); + assert_se(strv_consume(&strv2, un) >= 0); + } + + assert_se(strv_equal(strv, strv2)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_serialize_item(); + test_serialize_item_escaped(); + test_serialize_usec(); + test_serialize_strv(); + + return EXIT_SUCCESS; +} From fa2951def756e396c92cf18f5aea70cdad311da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 26 Oct 2018 13:17:44 +0200 Subject: [PATCH 4/5] test-serialize: allocate long_string dynamically --- src/test/test-serialize.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/test-serialize.c b/src/test/test-serialize.c index 5959455411..e38b48fdbc 100644 --- a/src/test/test-serialize.c +++ b/src/test/test-serialize.c @@ -10,11 +10,7 @@ #include "strv.h" #include "tests.h" -#define sixteen(x) x x x x x x x x x x x x x x x x -#define million(x) sixteen(sixteen(sixteen(sixteen(sixteen(x))))) - -#define long_string million("x") -assert_cc(STRLEN(long_string) == LONG_LINE_MAX); +char long_string[LONG_LINE_MAX+1]; static void test_serialize_item(void) { _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; @@ -140,6 +136,9 @@ static void test_serialize_strv(void) { int main(int argc, char *argv[]) { test_setup_logging(LOG_INFO); + memset(long_string, 'x', sizeof(long_string)-1); + char_array_0(long_string); + test_serialize_item(); test_serialize_item_escaped(); test_serialize_usec(); From 1c1d719aecdb67d2d8098befa884d45fa76cb84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 26 Oct 2018 12:30:04 +0200 Subject: [PATCH 5/5] Move tests for *serialize_environment into test-serialize.c The implementation is in serialize.c. --- src/test/test-env-util.c | 57 ------------------------------------ src/test/test-serialize.c | 61 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c index 815fb340af..ee9734fd66 100644 --- a/src/test/test-env-util.c +++ b/src/test/test-env-util.c @@ -306,61 +306,6 @@ static void test_env_assignment_is_valid(void) { assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;\x07\"")); } -static void test_deserialize_environment(void) { - _cleanup_strv_free_ char **env; - - assert_se(env = strv_new("A=1", NULL)); - - assert_se(deserialize_environment("B=2", &env) >= 0); - assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0); - - assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e"))); - - assert_se(deserialize_environment("foo\\", &env) < 0); - assert_se(deserialize_environment("bar\\_baz", &env) < 0); -} - -static void test_serialize_environment(void) { - _cleanup_strv_free_ char **env = NULL, **env2 = NULL; - _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX"; - _cleanup_fclose_ FILE *f = NULL; - int r; - - assert_se(env = strv_new("A=1", - "B=2", - "C=ąęółń", - "D=D=a\\x0Ab", - "FOO%%=a\177b\nc\td e", - NULL)); - - assert_se(fmkostemp_safe(fn, "r+", &f) == 0); - assert_se(serialize_strv(f, "env", env) == 1); - assert_se(fflush_and_check(f) == 0); - - rewind(f); - - for (;;) { - _cleanup_free_ char *line = NULL; - const char *l; - - r = read_line(f, LONG_LINE_MAX, &line); - assert_se(r >= 0); - - if (r == 0) - break; - - l = strstrip(line); - - assert_se(startswith(l, "env=")); - - r = deserialize_environment(l+4, &env2); - assert_se(r >= 0); - } - assert_se(feof(f)); - - assert_se(strv_equal(env, env2)); -} - int main(int argc, char *argv[]) { test_strv_env_delete(); test_strv_env_get(); @@ -377,8 +322,6 @@ int main(int argc, char *argv[]) { test_env_name_is_valid(); test_env_value_is_valid(); test_env_assignment_is_valid(); - test_deserialize_environment(); - test_serialize_environment(); return 0; } diff --git a/src/test/test-serialize.c b/src/test/test-serialize.c index e38b48fdbc..b70eb3daa7 100644 --- a/src/test/test-serialize.c +++ b/src/test/test-serialize.c @@ -133,6 +133,65 @@ static void test_serialize_strv(void) { assert_se(strv_equal(strv, strv2)); } +static void test_deserialize_environment(void) { + _cleanup_strv_free_ char **env; + + log_info("/* %s */", __func__); + + assert_se(env = strv_new("A=1", NULL)); + + assert_se(deserialize_environment("B=2", &env) >= 0); + assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0); + + assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e"))); + + assert_se(deserialize_environment("foo\\", &env) < 0); + assert_se(deserialize_environment("bar\\_baz", &env) < 0); +} + +static void test_serialize_environment(void) { + _cleanup_strv_free_ char **env = NULL, **env2 = NULL; + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(env = strv_new("A=1", + "B=2", + "C=ąęółń", + "D=D=a\\x0Ab", + "FOO%%=a\177b\nc\td e", + NULL)); + + assert_se(serialize_strv(f, "env", env) == 1); + assert_se(fflush_and_check(f) == 0); + + rewind(f); + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + assert_se(r >= 0); + + if (r == 0) + break; + + l = strstrip(line); + + assert_se(startswith(l, "env=")); + + r = deserialize_environment(l+4, &env2); + assert_se(r >= 0); + } + assert_se(feof(f)); + + assert_se(strv_equal(env, env2)); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_INFO); @@ -143,6 +202,8 @@ int main(int argc, char *argv[]) { test_serialize_item_escaped(); test_serialize_usec(); test_serialize_strv(); + test_deserialize_environment(); + test_serialize_environment(); return EXIT_SUCCESS; }