summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/test-calendarspec.c1
-rw-r--r--src/test/test-cgroup-mask.c6
-rw-r--r--src/test/test-cgroup-util.c47
-rw-r--r--src/test/test-conf-files.c24
-rw-r--r--src/test/test-copy.c25
-rw-r--r--src/test/test-dns-domain.c8
-rw-r--r--src/test/test-engine.c5
-rw-r--r--src/test/test-env-util.c117
-rw-r--r--src/test/test-exec-util.c348
-rw-r--r--src/test/test-execute.c57
-rw-r--r--src/test/test-fd-util.c10
-rw-r--r--src/test/test-fileio.c112
-rw-r--r--src/test/test-ipcrm.c2
-rw-r--r--src/test/test-journal-importer.c90
-rw-r--r--src/test/test-path.c2
-rw-r--r--src/test/test-sched-prio.c5
-rw-r--r--src/test/test-socket-util.c19
-rw-r--r--src/test/test-stat-util.c12
-rw-r--r--src/test/test-util.c45
19 files changed, 838 insertions, 97 deletions
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 1f34a91b10..f90b73aeaf 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -192,6 +192,7 @@ int main(int argc, char* argv[]) {
test_one("00..07-*-*", "2000..2007-*-* 00:00:00");
test_one("*:20..39/5", "*-*-* *:20..35/5:00");
test_one("00:00:20..40/1", "*-*-* 00:00:20..40");
+ test_one("*~03/1,03..05", "*-*~03/1,03..05 00:00:00");
test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index a027eb0fd2..b42088c680 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -27,6 +27,7 @@
#include "unit.h"
static int test_cgroup_mask(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
Manager *m = NULL;
Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep;
FILE *serial = NULL;
@@ -34,7 +35,8 @@ static int test_cgroup_mask(void) {
int r;
/* Prepare the manager. */
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, true, &m);
if (r == -EPERM || r == -EACCES) {
puts("manager_new: Permission denied. Skipping test.");
@@ -110,10 +112,8 @@ static int test_cgroup_mask(void) {
}
int main(int argc, char* argv[]) {
- _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int rc = 0;
- assert_se(runtime_dir = setup_fake_runtime_dir());
TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask());
return rc;
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index c60fb631fa..30cd463722 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -18,11 +18,13 @@
***/
#include "alloc-util.h"
+#include "build.h"
#include "cgroup-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "stat-util.h"
#include "string-util.h"
@@ -332,7 +334,49 @@ static void test_fd_is_cgroup_fs(void) {
fd = safe_close(fd);
}
+static void test_is_wanted_print(bool header) {
+ _cleanup_free_ char *cmdline = NULL;
+
+ log_info("-- %s --", __func__);
+ assert_se(proc_cmdline(&cmdline) >= 0);
+ log_info("cmdline: %s", cmdline);
+ if (header) {
+
+ log_info(_CGROUP_HIEARCHY_);
+ (void) system("findmnt -n /sys/fs/cgroup");
+ }
+
+ log_info("is_unified_wanted() → %s", yes_no(cg_is_unified_wanted()));
+ log_info("is_hybrid_wanted() → %s", yes_no(cg_is_hybrid_wanted()));
+ log_info("is_legacy_wanted() → %s", yes_no(cg_is_legacy_wanted()));
+ log_info(" ");
+}
+
+static void test_is_wanted(void) {
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "systemd.unified_cgroup_hierarchy", 1) >= 0);
+ test_is_wanted_print(false);
+
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "systemd.unified_cgroup_hierarchy=0", 1) >= 0);
+ test_is_wanted_print(false);
+
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "systemd.unified_cgroup_hierarchy=0 "
+ "systemd.legacy_systemd_cgroup_controller", 1) >= 0);
+ test_is_wanted_print(false);
+
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "systemd.unified_cgroup_hierarchy=0 "
+ "systemd.legacy_systemd_cgroup_controller=0", 1) >= 0);
+ test_is_wanted_print(false);
+}
+
int main(void) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
test_path_decode_unit();
test_path_get_unit();
test_path_get_user_unit();
@@ -349,6 +393,9 @@ int main(void) {
TEST_REQ_RUNNING_SYSTEMD(test_mask_supported());
TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs());
TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs());
+ test_is_wanted_print(true);
+ test_is_wanted_print(false); /* run twice to test caching */
+ test_is_wanted();
return 0;
}
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 03b3a9fa5c..22b7c61204 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -47,13 +47,16 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
static void test_conf_files_list(bool use_root) {
char tmp_dir[] = "/tmp/test-conf-files-XXXXXX";
- _cleanup_strv_free_ char **found_files = NULL;
- const char *root_dir, *search_1, *search_2, *expect_a, *expect_b;
+ _cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL;
+ const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c;
+
+ log_debug("/* %s */", __func__);
setup_test_dir(tmp_dir,
"/dir1/a.conf",
"/dir2/a.conf",
"/dir2/b.conf",
+ "/dir2/c.foo",
NULL);
if (use_root) {
@@ -68,6 +71,9 @@ static void test_conf_files_list(bool use_root) {
expect_a = strjoina(tmp_dir, "/dir1/a.conf");
expect_b = strjoina(tmp_dir, "/dir2/b.conf");
+ expect_c = strjoina(tmp_dir, "/dir2/c.foo");
+
+ log_debug("/* Check when filtered by suffix */");
assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0);
strv_print(found_files);
@@ -77,10 +83,24 @@ static void test_conf_files_list(bool use_root) {
assert_se(streq_ptr(found_files[1], expect_b));
assert_se(found_files[2] == NULL);
+ log_debug("/* Check when unfiltered */");
+ assert_se(conf_files_list(&found_files2, NULL, root_dir, search_1, search_2, NULL) == 0);
+ strv_print(found_files2);
+
+ assert_se(found_files2);
+ assert_se(streq_ptr(found_files2[0], expect_a));
+ assert_se(streq_ptr(found_files2[1], expect_b));
+ assert_se(streq_ptr(found_files2[2], expect_c));
+ assert_se(found_files2[3] == NULL);
+
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
test_conf_files_list(false);
test_conf_files_list(true);
return 0;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index e65516f080..ed6725611d 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -31,6 +31,7 @@
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
static void test_copy_file(void) {
@@ -52,7 +53,7 @@ static void test_copy_file(void) {
assert_se(write_string_file(fn, "foo bar bar bar foo", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
+ assert_se(copy_file(fn, fn_copy, 0, 0644, 0, COPY_REFLINK) == 0);
assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
assert_se(streq(buf, "foo bar bar bar foo\n"));
@@ -77,8 +78,8 @@ static void test_copy_file_fd(void) {
assert_se(out_fd >= 0);
assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0);
- assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0);
- assert_se(copy_file_fd(in_fn, out_fd, true) >= 0);
+ assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, COPY_REFLINK) < 0);
+ assert_se(copy_file_fd(in_fn, out_fd, COPY_REFLINK) >= 0);
assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
@@ -125,7 +126,7 @@ static void test_copy_tree(void) {
unixsockp = strjoina(original_dir, "unixsock");
assert_se(mknod(unixsockp, S_IFSOCK|0644, 0) >= 0);
- assert_se(copy_tree(original_dir, copy_dir, true) == 0);
+ assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0);
STRV_FOREACH(p, files) {
_cleanup_free_ char *buf = NULL, *f;
@@ -152,8 +153,8 @@ static void test_copy_tree(void) {
assert_se(stat(unixsockp, &st) >= 0);
assert_se(S_ISSOCK(st.st_mode));
- assert_se(copy_tree(original_dir, copy_dir, false) < 0);
- assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, false) < 0);
+ assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0);
+ assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0);
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -172,7 +173,7 @@ static void test_copy_bytes(void) {
assert_se(pipe2(pipefd, O_CLOEXEC) == 0);
- r = copy_bytes(infd, pipefd[1], (uint64_t) -1, false);
+ r = copy_bytes(infd, pipefd[1], (uint64_t) -1, 0);
assert_se(r == 0);
r = read(pipefd[0], buf, sizeof(buf));
@@ -185,13 +186,13 @@ static void test_copy_bytes(void) {
assert_se(strneq(buf, buf2, r));
/* test copy_bytes with invalid descriptors */
- r = copy_bytes(pipefd[0], pipefd[0], 1, false);
+ r = copy_bytes(pipefd[0], pipefd[0], 1, 0);
assert_se(r == -EBADF);
- r = copy_bytes(pipefd[1], pipefd[1], 1, false);
+ r = copy_bytes(pipefd[1], pipefd[1], 1, 0);
assert_se(r == -EBADF);
- r = copy_bytes(pipefd[1], infd, 1, false);
+ r = copy_bytes(pipefd[1], infd, 1, 0);
assert_se(r == -EBADF);
}
@@ -213,7 +214,7 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint
fd3 = mkostemp_safe(fn3);
assert_se(fd3 >= 0);
- r = copy_bytes(fd, fd2, max_bytes, try_reflink);
+ r = copy_bytes(fd, fd2, max_bytes, try_reflink ? COPY_REFLINK : 0);
if (max_bytes == (uint64_t) -1)
assert_se(r == 0);
else
@@ -221,7 +222,7 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint
assert_se(lseek(fd2, 0, SEEK_SET) == 0);
- r = copy_bytes(fd2, fd3, max_bytes, try_reflink);
+ r = copy_bytes(fd2, fd3, max_bytes, try_reflink ? COPY_REFLINK : 0);
if (max_bytes == (uint64_t) -1)
assert_se(r == 0);
else
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index b4db4a6702..a7cd8e4b51 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -373,16 +373,16 @@ static void test_dns_name_is_valid(void) {
test_dns_name_is_valid_one("ä", 1);
test_dns_name_is_valid_one("\n", 0);
- /* 256 characters*/
+ /* 256 characters */
test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345", 0);
- /* 255 characters*/
+ /* 255 characters */
test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a1234", 0);
- /* 254 characters*/
+ /* 254 characters */
test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", 0);
- /* 253 characters*/
+ /* 253 characters */
test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", 1);
/* label of 64 chars length */
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index a651f6b683..8133343fb3 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -37,10 +37,9 @@ int main(int argc, char *argv[]) {
Job *j;
int r;
- assert_se(runtime_dir = setup_fake_runtime_dir());
-
/* prepare the test */
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, true, &m);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c
index 35bb62906e..e5cc2a2df8 100644
--- a/src/test/test-env-util.c
+++ b/src/test/test-env-util.c
@@ -45,6 +45,16 @@ static void test_strv_env_delete(void) {
assert_se(strv_length(d) == 2);
}
+static void test_strv_env_get(void) {
+ char **l;
+
+ l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
+
+ assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2"));
+ assert_se(streq(strv_env_get(l, "THREE"), "3"));
+ assert_se(streq(strv_env_get(l, "FOUR"), "4"));
+}
+
static void test_strv_env_unset(void) {
_cleanup_strv_free_ char **l = NULL;
@@ -102,7 +112,90 @@ static void test_strv_env_merge(void) {
assert_se(strv_length(r) == 5);
}
-static void test_replace_env_arg(void) {
+static void test_env_strv_get_n(void) {
+ const char *_env[] = {
+ "FOO=NO NO NO",
+ "FOO=BAR BAR",
+ "BAR=waldo",
+ "PATH=unset",
+ NULL
+ };
+ char **env = (char**) _env;
+
+ assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR"));
+ assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
+ assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR"));
+ assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
+
+ assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset"));
+ assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset"));
+ assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
+ assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
+
+ env[3] = NULL; /* kill our $PATH */
+
+ assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
+ assert_se(!strv_env_get_n(env, "PATH", 4, 0));
+ assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
+ getenv("PATH")));
+ assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
+ getenv("PATH")));
+}
+
+static void test_replace_env(bool braceless) {
+ const char *env[] = {
+ "FOO=BAR BAR",
+ "BAR=waldo",
+ NULL
+ };
+ _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL;
+ unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless;
+
+ t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags);
+ assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR"));
+
+ s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags);
+ assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
+
+ q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags);
+ assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR="));
+
+ r = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags);
+ assert_se(streq(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
+
+ p = replace_env("${BAR}$BAR$BAR", (char**) env, flags);
+ assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR"));
+}
+
+static void test_replace_env2(bool extended) {
+ const char *env[] = {
+ "FOO=foo",
+ "BAR=bar",
+ NULL
+ };
+ _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL;
+ unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended;
+
+ t = replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags);
+ assert_se(streq(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}"));
+
+ s = replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags);
+ assert_se(streq(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}"));
+
+ q = replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags);
+ assert_se(streq(q, extended ? "XXX=" : "XXX=${XXX:+bar}"));
+
+ r = replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags);
+ assert_se(streq(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}"));
+
+ p = replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags);
+ assert_se(streq(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}"));
+
+ x = replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags);
+ assert_se(streq(x, extended ? "XXX=" : "XXX=${XXX:+barpost}"));
+}
+
+static void test_replace_env_argv(void) {
const char *env[] = {
"FOO=BAR BAR",
"BAR=waldo",
@@ -120,6 +213,12 @@ static void test_replace_env_arg(void) {
"${FOO",
"FOO$$${FOO}",
"$$FOO${FOO}",
+ "${FOO:-${BAR}}",
+ "${QUUX:-${FOO}}",
+ "${FOO:+${BAR}}",
+ "${QUUX:+${BAR}}",
+ "${FOO:+|${BAR}|}}",
+ "${FOO:+|${BAR}{|}",
NULL
};
_cleanup_strv_free_ char **r = NULL;
@@ -137,7 +236,13 @@ static void test_replace_env_arg(void) {
assert_se(streq(r[8], "${FOO"));
assert_se(streq(r[9], "FOO$BAR BAR"));
assert_se(streq(r[10], "$FOOBAR BAR"));
- assert_se(strv_length(r) == 11);
+ assert_se(streq(r[11], "${FOO:-waldo}"));
+ assert_se(streq(r[12], "${QUUX:-BAR BAR}"));
+ assert_se(streq(r[13], "${FOO:+waldo}"));
+ assert_se(streq(r[14], "${QUUX:+waldo}"));
+ assert_se(streq(r[15], "${FOO:+|waldo|}}"));
+ assert_se(streq(r[16], "${FOO:+|waldo{|}"));
+ assert_se(strv_length(r) == 17);
}
static void test_env_clean(void) {
@@ -211,10 +316,16 @@ static void test_env_assignment_is_valid(void) {
int main(int argc, char *argv[]) {
test_strv_env_delete();
+ test_strv_env_get();
test_strv_env_unset();
test_strv_env_set();
test_strv_env_merge();
- test_replace_env_arg();
+ test_env_strv_get_n();
+ test_replace_env(false);
+ test_replace_env(true);
+ test_replace_env2(false);
+ test_replace_env2(true);
+ test_replace_env_argv();
test_env_clean();
test_env_name_is_valid();
test_env_value_is_valid();
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
new file mode 100644
index 0000000000..482b0751b9
--- /dev/null
+++ b/src/test/test-exec-util.c
@@ -0,0 +1,348 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2013 Thomas H.P. Andersen
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "copy.h"
+#include "def.h"
+#include "env-util.h"
+#include "exec-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "log.h"
+#include "macro.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+
+static int here = 0, here2 = 0, here3 = 0;
+void *ignore_stdout_args[] = {&here, &here2, &here3};
+
+/* noop handlers, just check that arguments are passed correctly */
+static int ignore_stdout_func(int fd, void *arg) {
+ assert(fd >= 0);
+ assert(arg == &here);
+ safe_close(fd);
+
+ return 0;
+}
+static int ignore_stdout_func2(int fd, void *arg) {
+ assert(fd >= 0);
+ assert(arg == &here2);
+ safe_close(fd);
+
+ return 0;
+}
+static int ignore_stdout_func3(int fd, void *arg) {
+ assert(fd >= 0);
+ assert(arg == &here3);
+ safe_close(fd);
+
+ return 0;
+}
+
+static const gather_stdout_callback_t ignore_stdout[] = {
+ ignore_stdout_func,
+ ignore_stdout_func2,
+ ignore_stdout_func3,
+};
+
+static void test_execute_directory(bool gather_stdout) {
+ char template_lo[] = "/tmp/test-exec-util.XXXXXXX";
+ char template_hi[] = "/tmp/test-exec-util.XXXXXXX";
+ const char * dirs[] = {template_hi, template_lo, NULL};
+ const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
+
+ log_info("/* %s (%s) */", __func__, gather_stdout ? "gathering stdout" : "asynchronous");
+
+ assert_se(mkdtemp(template_lo));
+ assert_se(mkdtemp(template_hi));
+
+ name = strjoina(template_lo, "/script");
+ name2 = strjoina(template_hi, "/script2");
+ name3 = strjoina(template_lo, "/useless");
+ overridden = strjoina(template_lo, "/overridden");
+ override = strjoina(template_hi, "/overridden");
+ masked = strjoina(template_lo, "/masked");
+ mask = strjoina(template_hi, "/masked");
+
+ assert_se(write_string_file(name,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name2,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(overridden,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(override,
+ "#!/bin/sh\necho 'Executing '$0",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(masked,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(symlink("/dev/null", mask) == 0);
+ assert_se(touch(name3) >= 0);
+
+ assert_se(chmod(name, 0755) == 0);
+ assert_se(chmod(name2, 0755) == 0);
+ assert_se(chmod(overridden, 0755) == 0);
+ assert_se(chmod(override, 0755) == 0);
+ assert_se(chmod(masked, 0755) == 0);
+
+ if (gather_stdout)
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+ else
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL);
+
+ assert_se(chdir(template_lo) == 0);
+ assert_se(access("it_works", F_OK) >= 0);
+ assert_se(access("failed", F_OK) < 0);
+
+ assert_se(chdir(template_hi) == 0);
+ assert_se(access("it_works2", F_OK) >= 0);
+ assert_se(access("failed", F_OK) < 0);
+
+ (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
+static void test_execution_order(void) {
+ char template_lo[] = "/tmp/test-exec-util-lo.XXXXXXX";
+ char template_hi[] = "/tmp/test-exec-util-hi.XXXXXXX";
+ const char *dirs[] = {template_hi, template_lo, NULL};
+ const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
+ const char *output, *t;
+ _cleanup_free_ char *contents = NULL;
+
+ assert_se(mkdtemp(template_lo));
+ assert_se(mkdtemp(template_hi));
+
+ output = strjoina(template_hi, "/output");
+
+ log_info("/* %s >>%s */", __func__, output);
+
+ /* write files in "random" order */
+ name2 = strjoina(template_lo, "/90-bar");
+ name = strjoina(template_hi, "/80-foo");
+ name3 = strjoina(template_lo, "/last");
+ overridden = strjoina(template_lo, "/30-override");
+ override = strjoina(template_hi, "/30-override");
+ masked = strjoina(template_lo, "/10-masked");
+ mask = strjoina(template_hi, "/10-masked");
+
+ t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
+ assert_se(write_string_file(name, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
+ assert_se(write_string_file(name2, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
+ assert_se(write_string_file(name3, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ t = strjoina("#!/bin/sh\necho OVERRIDDEN >>", output);
+ assert_se(write_string_file(overridden, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
+ assert_se(write_string_file(override, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ t = strjoina("#!/bin/sh\necho MASKED >>", output);
+ assert_se(write_string_file(masked, t, WRITE_STRING_FILE_CREATE) == 0);
+
+ assert_se(symlink("/dev/null", mask) == 0);
+
+ assert_se(chmod(name, 0755) == 0);
+ assert_se(chmod(name2, 0755) == 0);
+ assert_se(chmod(name3, 0755) == 0);
+ assert_se(chmod(overridden, 0755) == 0);
+ assert_se(chmod(override, 0755) == 0);
+ assert_se(chmod(masked, 0755) == 0);
+
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+
+ assert_se(read_full_file(output, &contents, NULL) >= 0);
+ assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n"));
+
+ (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
+static int gather_stdout_one(int fd, void *arg) {
+ char ***s = arg, *t;
+ char buf[128] = {};
+
+ assert_se(s);
+ assert_se(read(fd, buf, sizeof buf) >= 0);
+ safe_close(fd);
+
+ assert_se(t = strndup(buf, sizeof buf));
+ assert_se(strv_push(s, t) >= 0);
+
+ return 0;
+}
+static int gather_stdout_two(int fd, void *arg) {
+ char ***s = arg, **t;
+
+ STRV_FOREACH(t, *s)
+ assert_se(write(fd, *t, strlen(*t)) == (ssize_t) strlen(*t));
+ safe_close(fd);
+
+ return 0;
+}
+static int gather_stdout_three(int fd, void *arg) {
+ char **s = arg;
+ char buf[128] = {};
+
+ assert_se(read(fd, buf, sizeof buf - 1) > 0);
+ safe_close(fd);
+ assert_se(*s = strndup(buf, sizeof buf));
+
+ return 0;
+}
+
+const gather_stdout_callback_t const gather_stdout[] = {
+ gather_stdout_one,
+ gather_stdout_two,
+ gather_stdout_three,
+};
+
+
+static void test_stdout_gathering(void) {
+ char template[] = "/tmp/test-exec-util.XXXXXXX";
+ const char *dirs[] = {template, NULL};
+ const char *name, *name2, *name3;
+ int r;
+
+ char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
+ _cleanup_free_ char *output = NULL;
+
+ void* args[] = {&tmp, &tmp, &output};
+
+ assert_se(mkdtemp(template));
+
+ log_info("/* %s */", __func__);
+
+ /* write files */
+ name = strjoina(template, "/10-foo");
+ name2 = strjoina(template, "/20-bar");
+ name3 = strjoina(template, "/30-last");
+
+ assert_se(write_string_file(name,
+ "#!/bin/sh\necho a\necho b\necho c\n",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name2,
+ "#!/bin/sh\necho d\n",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name3,
+ "#!/bin/sh\nsleep 1",
+ WRITE_STRING_FILE_CREATE) == 0);
+
+ assert_se(chmod(name, 0755) == 0);
+ assert_se(chmod(name2, 0755) == 0);
+ assert_se(chmod(name3, 0755) == 0);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL);
+ assert_se(r >= 0);
+
+ log_info("got: %s", output);
+
+ assert_se(streq(output, "a\nb\nc\nd\n"));
+}
+
+static void test_environment_gathering(void) {
+ char template[] = "/tmp/test-exec-util.XXXXXXX", **p;
+ const char *dirs[] = {template, NULL};
+ const char *name, *name2, *name3;
+ int r;
+
+ char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
+ _cleanup_strv_free_ char **env = NULL;
+
+ void* const args[] = { &tmp, &tmp, &env };
+
+ assert_se(mkdtemp(template));
+
+ log_info("/* %s */", __func__);
+
+ /* write files */
+ name = strjoina(template, "/10-foo");
+ name2 = strjoina(template, "/20-bar");
+ name3 = strjoina(template, "/30-last");
+
+ assert_se(write_string_file(name,
+ "#!/bin/sh\n"
+ "echo A=23\n",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name2,
+ "#!/bin/sh\n"
+ "echo A=22:$A\n\n\n", /* substitution from previous generator */
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name3,
+ "#!/bin/sh\n"
+ "echo A=$A:24\n"
+ "echo B=12\n"
+ "echo C=000\n"
+ "echo C=001\n" /* variable overwriting */
+ /* various invalid entries */
+ "echo unset A\n"
+ "echo unset A=\n"
+ "echo unset A=B\n"
+ "echo unset \n"
+ "echo A B=C\n"
+ "echo A\n"
+ /* test variable assignment without newline */
+ "echo PATH=$PATH:/no/such/file", /* no newline */
+ WRITE_STRING_FILE_CREATE) == 0);
+
+ assert_se(chmod(name, 0755) == 0);
+ assert_se(chmod(name2, 0755) == 0);
+ assert_se(chmod(name3, 0755) == 0);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+ assert_se(r >= 0);
+
+ STRV_FOREACH(p, env)
+ log_info("got env: \"%s\"", *p);
+
+ assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
+ assert_se(streq(strv_env_get(env, "B"), "12"));
+ assert_se(streq(strv_env_get(env, "C"), "001"));
+ assert_se(endswith(strv_env_get(env, "PATH"), ":/no/such/file"));
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_execute_directory(true);
+ test_execute_directory(false);
+ test_execution_order();
+ test_stdout_gathering();
+ test_environment_gathering();
+
+ return 0;
+}
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index bc9a2021f9..90540b884b 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -35,6 +35,7 @@
#endif
#include "stat-util.h"
#include "test-helper.h"
+#include "tests.h"
#include "unit.h"
#include "util.h"
#include "virt.h"
@@ -145,11 +146,11 @@ static void test_exec_privatetmp(Manager *m) {
static void test_exec_privatedevices(Manager *m) {
if (detect_container() > 0) {
- log_notice("testing in container, skipping private device tests");
+ log_notice("testing in container, skipping %s", __func__);
return;
}
if (!is_inaccessible_available()) {
- log_notice("testing without inaccessible, skipping private device tests");
+ log_notice("testing without inaccessible, skipping %s", __func__);
return;
}
@@ -158,12 +159,22 @@ static void test_exec_privatedevices(Manager *m) {
}
static void test_exec_privatedevices_capabilities(Manager *m) {
+ int r;
+
if (detect_container() > 0) {
- log_notice("testing in container, skipping private device tests");
+ log_notice("testing in container, skipping %s", __func__);
return;
}
if (!is_inaccessible_available()) {
- log_notice("testing without inaccessible, skipping private device tests");
+ log_notice("testing without inaccessible, skipping %s", __func__);
+ return;
+ }
+
+ /* We use capsh to test if the capabilities are
+ * properly set, so be sure that it exists */
+ r = find_binary("capsh", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
return;
}
@@ -174,15 +185,24 @@ static void test_exec_privatedevices_capabilities(Manager *m) {
}
static void test_exec_protectkernelmodules(Manager *m) {
+ int r;
+
if (detect_container() > 0) {
- log_notice("testing in container, skipping protectkernelmodules tests");
+ log_notice("testing in container, skipping %s", __func__);
return;
}
if (!is_inaccessible_available()) {
- log_notice("testing without inaccessible, skipping protectkernelmodules tests");
+ log_notice("testing without inaccessible, skipping %s", __func__);
return;
}
+ r = find_binary("capsh", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
+ return;
+ }
+
+
test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
@@ -253,7 +273,7 @@ static void test_exec_systemcall_system_mode_with_user(Manager *m) {
else if (getpwnam("nfsnobody"))
test(m, "exec-systemcallfilter-system-user-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_systemcall_system_mode_with_user, could not find nobody/nfsnobody user: %m");
+ log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
#endif
}
@@ -263,7 +283,7 @@ static void test_exec_user(Manager *m) {
else if (getpwnam("nfsnobody"))
test(m, "exec-user-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_user, could not find nobody/nfsnobody user: %m");
+ log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
}
static void test_exec_group(Manager *m) {
@@ -272,7 +292,7 @@ static void test_exec_group(Manager *m) {
else if (getgrnam("nfsnobody"))
test(m, "exec-group-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_group, could not find nobody/nfsnobody group: %m");
+ log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody group: %m", __func__);
}
static void test_exec_supplementary_groups(Manager *m) {
@@ -353,17 +373,15 @@ static void test_exec_runtimedirectory(Manager *m) {
else if (getgrnam("nfsnobody"))
test(m, "exec-runtimedirectory-owner-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody/nfsnobody group: %m");
+ log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody group: %m", __func__);
}
static void test_exec_capabilityboundingset(Manager *m) {
int r;
- /* We use capsh to test if the capabilities are
- * properly set, so be sure that it exists */
r = find_binary("capsh", NULL);
if (r < 0) {
- log_error_errno(r, "Skipping test_exec_capabilityboundingset, could not find capsh binary: %m");
+ log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
return;
}
@@ -389,9 +407,9 @@ static void test_exec_capabilityambientset(Manager *m) {
test(m, "exec-capabilityambientset-nfsnobody.service", 0, CLD_EXITED);
test(m, "exec-capabilityambientset-merge-nfsnobody.service", 0, CLD_EXITED);
} else
- log_error_errno(errno, "Skipping test_exec_capabilityambientset, could not find nobody/nfsnobody user: %m");
+ log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
} else
- log_error_errno(errno, "Skipping test_exec_capabilityambientset, the kernel does not support ambient capabilities: %m");
+ log_error_errno(errno, "Skipping %s, the kernel does not support ambient capabilities: %m", __func__);
}
static void test_exec_privatenetwork(Manager *m) {
@@ -399,7 +417,7 @@ static void test_exec_privatenetwork(Manager *m) {
r = find_binary("ip", NULL);
if (r < 0) {
- log_error_errno(r, "Skipping test_exec_privatenetwork, could not find ip binary: %m");
+ log_error_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
return;
}
@@ -422,6 +440,10 @@ static void test_exec_spec_interpolation(Manager *m) {
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
}
+static void test_exec_read_only_path_suceed(Manager *m) {
+ test(m, "exec-read-only-path-succeed.service", 0, CLD_EXITED);
+}
+
static int run_tests(UnitFileScope scope, const test_function_t *tests) {
const test_function_t *test = NULL;
Manager *m = NULL;
@@ -475,6 +497,7 @@ int main(int argc, char *argv[]) {
test_exec_oomscoreadjust,
test_exec_ioschedulingclass,
test_exec_spec_interpolation,
+ test_exec_read_only_path_suceed,
NULL,
};
static const test_function_t system_tests[] = {
@@ -494,7 +517,7 @@ int main(int argc, char *argv[]) {
}
assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
- assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0);
+ assert_se(set_unit_path(get_testdata_dir("/test-execute")) >= 0);
/* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
* cases, otherwise (and if they are present in the environment),
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
index f555bb976c..4425b5fe5f 100644
--- a/src/test/test-fd-util.c
+++ b/src/test/test-fd-util.c
@@ -94,10 +94,20 @@ static void test_same_fd(void) {
assert_se(same_fd(b, a) == 0);
}
+static void test_open_serialization_fd(void) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open_serialization_fd("test");
+ assert_se(fd >= 0);
+
+ write(fd, "test\n", 5);
+}
+
int main(int argc, char *argv[]) {
test_close_many();
test_close_nointr();
test_same_fd();
+ test_open_serialization_fd();
return 0;
}
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 56316904a3..b1d688c89e 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -71,6 +71,8 @@ static void test_parse_env_file(void) {
"seven=\"sevenval\" #nocomment\n"
"eight=eightval #nocomment\n"
"export nine=nineval\n"
+ "ten=ignored\n"
+ "ten=ignored\n"
"ten=", f);
fflush(f);
@@ -204,6 +206,113 @@ static void test_parse_multiline_env_file(void) {
unlink(p);
}
+static void test_merge_env_file(void) {
+ char t[] = "/tmp/test-fileio-XXXXXX";
+ int fd, r;
+ FILE *f;
+ _cleanup_strv_free_ char **a = NULL;
+ char **i;
+
+ fd = mkostemp_safe(t);
+ assert_se(fd >= 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"
+ "twentyone=2${one}\n"
+ "one=2\n"
+ "twentytwo=2${one}\n"
+ "xxx_minus_three=$xxx - 3\n"
+ "xxx=0x$one$one$one\n"
+ "yyy=${one:-fallback}\n"
+ "zzz=${one:+replacement}\n"
+ "zzzz=${foobar:-${nothing}}\n"
+ "zzzzz=${nothing:+${nothing}}\n"
+ , false);
+ assert(r >= 0);
+
+ r = merge_env_file(&a, NULL, t);
+ assert_se(r >= 0);
+ strv_sort(a);
+
+ 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);
+
+ r = merge_env_file(&a, NULL, t);
+ assert_se(r >= 0);
+ strv_sort(a);
+
+ 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);
+}
+
+static void test_merge_env_file_invalid(void) {
+ char t[] = "/tmp/test-fileio-XXXXXX";
+ int fd, r;
+ FILE *f;
+ _cleanup_strv_free_ char **a = NULL;
+ char **i;
+
+ fd = mkostemp_safe(t);
+ assert_se(fd >= 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"
+ "unset one=1 \n"
+ "one \n"
+ "one = \n"
+ "one two =\n"
+ "\x20two=\n"
+ "#comment=comment\n"
+ ";comment2=comment2\n"
+ "#\n"
+ "\n\n" /* empty line */
+ , false);
+ assert(r >= 0);
+
+ r = merge_env_file(&a, NULL, t);
+ assert_se(r >= 0);
+
+ STRV_FOREACH(i, a)
+ log_info("Got: <%s>", *i);
+
+ assert_se(strv_isempty(a));
+}
static void test_executable_is_script(void) {
char t[] = "/tmp/test-executable-XXXXXX";
@@ -555,11 +664,14 @@ static void test_tempfn(void) {
}
int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
log_parse_environment();
log_open();
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();
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 463e135e2b..ce6c7aa18a 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -24,7 +24,7 @@
int main(int argc, char *argv[]) {
uid_t uid;
int r;
- const char* name = argv[1] ?: "nfsnobody";
+ const char* name = argv[1] ?: NOBODY_USER_NAME;
r = get_user_creds(&name, &uid, NULL, NULL, NULL);
if (r < 0) {
diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c
new file mode 100644
index 0000000000..a61212ce7b
--- /dev/null
+++ b/src/test/test-journal-importer.c
@@ -0,0 +1,90 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "log.h"
+#include "journal-importer.h"
+#include "string-util.h"
+#include "tests.h"
+
+static void assert_iovec_entry(const struct iovec *iovec, const char* content) {
+ assert_se(strlen(content) == iovec->iov_len);
+ assert_se(memcmp(content, iovec->iov_base, iovec->iov_len) == 0);
+}
+
+#define COREDUMP_PROC_GROUP \
+ "COREDUMP_PROC_CGROUP=1:name=systemd:/\n" \
+ "0::/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service\n"
+
+static void test_basic_parsing(void) {
+ _cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ int r;
+
+ imp.fd = open(get_testdata_dir("/journal-data/journal-1.txt"), O_RDONLY|O_CLOEXEC);
+ assert_se(imp.fd >= 0);
+
+ do
+ r = journal_importer_process_data(&imp);
+ while (r == 0 && !journal_importer_eof(&imp));
+ assert_se(r == 1);
+
+ /* We read one entry, so we should get EOF on next read, but not yet */
+ assert_se(!journal_importer_eof(&imp));
+
+ assert_se(imp.iovw.count == 6);
+ assert_iovec_entry(&imp.iovw.iovec[0], "_BOOT_ID=1531fd22ec84429e85ae888b12fadb91");
+ assert_iovec_entry(&imp.iovw.iovec[1], "_TRANSPORT=journal");
+ assert_iovec_entry(&imp.iovw.iovec[2], COREDUMP_PROC_GROUP);
+ assert_iovec_entry(&imp.iovw.iovec[3], "COREDUMP_RLIMIT=-1");
+ assert_iovec_entry(&imp.iovw.iovec[4], COREDUMP_PROC_GROUP);
+ assert_iovec_entry(&imp.iovw.iovec[5], "_SOURCE_REALTIME_TIMESTAMP=1478389147837945");
+
+ /* Let's check if we get EOF now */
+ r = journal_importer_process_data(&imp);
+ assert_se(r == 0);
+ assert_se(journal_importer_eof(&imp));
+}
+
+static void test_bad_input(void) {
+ _cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ int r;
+
+ imp.fd = open(get_testdata_dir("/journal-data/journal-2.txt"), O_RDONLY|O_CLOEXEC);
+ assert_se(imp.fd >= 0);
+
+ do
+ r = journal_importer_process_data(&imp);
+ while (!journal_importer_eof(&imp));
+ assert_se(r == 0); /* If we don't have enough input, 0 is returned */
+
+ assert_se(journal_importer_eof(&imp));
+}
+
+int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ test_basic_parsing();
+ test_bad_input();
+
+ return 0;
+}
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 5e99d478ee..70ac6b3df3 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -262,8 +262,8 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+ assert_se(set_unit_path(get_testdata_dir("/test-path")) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
- assert_se(set_unit_path(TEST_DIR "/test-path/") >= 0);
for (test = tests; test && *test; test++) {
int r;
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index 7b37910c33..81d9abc2d5 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -34,10 +34,9 @@ int main(int argc, char *argv[]) {
FDSet *fdset = NULL;
int r;
- assert_se(runtime_dir = setup_fake_runtime_dir());
-
/* prepare the test */
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, true, &m);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index d80613dc84..8ac1d7989f 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -456,6 +456,23 @@ static void test_sockaddr_un_len(void) {
assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1));
}
+static void test_in_addr_is_multicast(void) {
+ union in_addr_union a, b;
+ int f;
+
+ assert_se(in_addr_from_string_auto("192.168.3.11", &f, &a) >= 0);
+ assert_se(in_addr_is_multicast(f, &a) == 0);
+
+ assert_se(in_addr_from_string_auto("224.0.0.1", &f, &a) >= 0);
+ assert_se(in_addr_is_multicast(f, &a) == 1);
+
+ assert_se(in_addr_from_string_auto("FF01:0:0:0:0:0:0:1", &f, &b) >= 0);
+ assert_se(in_addr_is_multicast(f, &b) == 1);
+
+ assert_se(in_addr_from_string_auto("2001:db8::c:69b:aeff:fe53:743e", &f, &b) >= 0);
+ assert_se(in_addr_is_multicast(f, &b) == 0);
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@@ -482,5 +499,7 @@ int main(int argc, char *argv[]) {
test_sockaddr_un_len();
+ test_in_addr_is_multicast();
+
return 0;
}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index a48dca99e1..3ff2aadea4 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -26,6 +26,7 @@
#include "fileio.h"
#include "macro.h"
#include "missing.h"
+#include "mount-util.h"
#include "stat-util.h"
static void test_files_same(void) {
@@ -69,8 +70,11 @@ static void test_path_is_os_tree(void) {
}
static void test_path_check_fstype(void) {
- assert_se(path_check_fstype("/run", TMPFS_MAGIC) > 0);
- assert_se(path_check_fstype("/run", BTRFS_SUPER_MAGIC) == 0);
+ /* run might not be a mount point in build chroots */
+ if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) {
+ assert_se(path_check_fstype("/run", TMPFS_MAGIC) > 0);
+ assert_se(path_check_fstype("/run", BTRFS_SUPER_MAGIC) == 0);
+ }
assert_se(path_check_fstype("/proc", PROC_SUPER_MAGIC) > 0);
assert_se(path_check_fstype("/proc", BTRFS_SUPER_MAGIC) == 0);
assert_se(path_check_fstype("/proc", BTRFS_SUPER_MAGIC) == 0);
@@ -78,7 +82,9 @@ static void test_path_check_fstype(void) {
}
static void test_path_is_temporary_fs(void) {
- assert_se(path_is_temporary_fs("/run") > 0);
+ /* run might not be a mount point in build chroots */
+ if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0)
+ assert_se(path_is_temporary_fs("/run") > 0);
assert_se(path_is_temporary_fs("/proc") == 0);
assert_se(path_is_temporary_fs("/i-dont-exist") == -ENOENT);
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 1b5cba86c1..f8bf0cb875 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -195,50 +195,6 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
-static void test_execute_directory(void) {
- char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
- char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
- const char * dirs[] = {template_hi, template_lo, NULL};
- const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
-
- assert_se(mkdtemp(template_lo));
- assert_se(mkdtemp(template_hi));
-
- name = strjoina(template_lo, "/script");
- name2 = strjoina(template_hi, "/script2");
- name3 = strjoina(template_lo, "/useless");
- overridden = strjoina(template_lo, "/overridden");
- override = strjoina(template_hi, "/overridden");
- masked = strjoina(template_lo, "/masked");
- mask = strjoina(template_hi, "/masked");
-
- assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
- assert_se(symlink("/dev/null", mask) == 0);
- assert_se(chmod(name, 0755) == 0);
- assert_se(chmod(name2, 0755) == 0);
- assert_se(chmod(overridden, 0755) == 0);
- assert_se(chmod(override, 0755) == 0);
- assert_se(chmod(masked, 0755) == 0);
- assert_se(touch(name3) >= 0);
-
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
-
- assert_se(chdir(template_lo) == 0);
- assert_se(access("it_works", F_OK) >= 0);
- assert_se(access("failed", F_OK) < 0);
-
- assert_se(chdir(template_hi) == 0);
- assert_se(access("it_works2", F_OK) >= 0);
- assert_se(access("failed", F_OK) < 0);
-
- (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
- (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
-}
-
static void test_raw_clone(void) {
pid_t parent, pid, pid2;
@@ -359,7 +315,6 @@ int main(int argc, char *argv[]) {
test_protect_errno();
test_in_set();
test_log2i();
- test_execute_directory();
test_raw_clone();
test_physical_memory();
test_physical_memory_scale();