summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2015-02-17 11:22:16 +0100
committerMartin Pitt <martin.pitt@ubuntu.com>2015-02-17 11:22:16 +0100
commite735f4d4eafc8c8c296cefc8228cf91c3fcfe822 (patch)
tree6626785ac2b212cc52282387a0a0d8a20fee8db2 /src/test
parentf47781d88ca6bf69d6b1dd0703b2b283482e5c09 (diff)
downloadsystemd-e735f4d4eafc8c8c296cefc8228cf91c3fcfe822.tar.gz
Imported Upstream version 219
Diffstat (limited to 'src/test')
-rw-r--r--src/test/test-async.c2
-rw-r--r--src/test/test-btrfs.c106
-rw-r--r--src/test/test-cap-list.c70
-rw-r--r--src/test/test-cgroup-util.c1
-rw-r--r--src/test/test-condition.c47
-rw-r--r--src/test/test-conf-files.c8
-rw-r--r--src/test/test-copy.c18
-rw-r--r--src/test/test-execute.c6
-rw-r--r--src/test/test-fileio.c2
-rw-r--r--src/test/test-fstab-util.c138
-rw-r--r--src/test/test-fw-util.c60
-rw-r--r--src/test/test-hashmap-plain.c7
-rw-r--r--src/test/test-json.c107
-rw-r--r--src/test/test-list.c45
-rw-r--r--src/test/test-loopback.c4
-rw-r--r--src/test/test-namespace.c5
-rw-r--r--src/test/test-path-lookup.c74
-rw-r--r--src/test/test-path-util.c4
-rw-r--r--src/test/test-path.c10
-rw-r--r--src/test/test-pty.c2
-rw-r--r--src/test/test-ring.c2
-rw-r--r--src/test/test-sigbus.c62
-rw-r--r--src/test/test-strbuf.c2
-rw-r--r--src/test/test-strv.c105
-rw-r--r--src/test/test-strxcpyx.c2
-rw-r--r--src/test/test-tables.c3
-rw-r--r--src/test/test-tmpfiles.c2
-rw-r--r--src/test/test-udev.c1
-rw-r--r--src/test/test-unit-file.c201
-rw-r--r--src/test/test-unit-name.c37
-rw-r--r--src/test/test-utf8.c13
-rw-r--r--src/test/test-util.c319
-rw-r--r--src/test/test-verbs.c78
33 files changed, 1391 insertions, 152 deletions
diff --git a/src/test/test-async.c b/src/test/test-async.c
index 401e68551e..abd36d693c 100644
--- a/src/test/test-async.c
+++ b/src/test/test-async.c
@@ -38,7 +38,9 @@ int main(int argc, char *argv[]) {
fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
assert_se(fd >= 0);
asynchronous_close(fd);
+
assert_se(asynchronous_job(async_func, NULL) >= 0);
+
assert_se(asynchronous_sync() >= 0);
sleep(1);
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
new file mode 100644
index 0000000000..150a32ad6f
--- /dev/null
+++ b/src/test/test-btrfs.c
@@ -0,0 +1,106 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ 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 <stdlib.h>
+#include <fcntl.h>
+
+#include "log.h"
+#include "fileio.h"
+#include "util.h"
+#include "btrfs-util.h"
+
+int main(int argc, char *argv[]) {
+ int r;
+ int fd;
+
+ fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+ if (fd < 0)
+ log_error_errno(errno, "Failed to open root directory: %m");
+ else {
+ BtrfsSubvolInfo info;
+ BtrfsQuotaInfo quota;
+ char ts[FORMAT_TIMESTAMP_MAX], bs[FORMAT_BYTES_MAX];
+
+ r = btrfs_subvol_get_info_fd(fd, &info);
+ if (r < 0)
+ log_error_errno(r, "Failed to get subvolume info: %m");
+ else {
+ log_info("otime: %s", format_timestamp(ts, sizeof(ts), info.otime));
+ log_info("read-only (search): %s", yes_no(info.read_only));
+ }
+
+ r = btrfs_subvol_get_quota_fd(fd, &quota);
+ if (r < 0)
+ log_error_errno(r, "Failed to get quota info: %m");
+ else {
+ log_info("referred: %s", strna(format_bytes(bs, sizeof(bs), quota.referred)));
+ log_info("exclusive: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive)));
+ log_info("referred_max: %s", strna(format_bytes(bs, sizeof(bs), quota.referred_max)));
+ log_info("exclusive_max: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive_max)));
+ }
+
+ r = btrfs_subvol_get_read_only_fd(fd);
+ if (r < 0)
+ log_error_errno(r, "Failed to get read only flag: %m");
+ else
+ log_info("read-only (ioctl): %s", yes_no(r));
+
+ safe_close(fd);
+ }
+
+ r = btrfs_subvol_make("/xxxtest");
+ if (r < 0)
+ log_error_errno(r, "Failed to make subvolume: %m");
+
+ r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha");
+ if (r < 0)
+ log_error_errno(r, "Failed to write file: %m");
+
+ r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", false, false);
+ if (r < 0)
+ log_error_errno(r, "Failed to make snapshot: %m");
+
+ r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", true, false);
+ if (r < 0)
+ log_error_errno(r, "Failed to make snapshot: %m");
+
+ r = btrfs_subvol_remove("/xxxtest");
+ if (r < 0)
+ log_error_errno(r, "Failed to remove subvolume: %m");
+
+ r = btrfs_subvol_remove("/xxxtest2");
+ if (r < 0)
+ log_error_errno(r, "Failed to remove subvolume: %m");
+
+ r = btrfs_subvol_remove("/xxxtest3");
+ if (r < 0)
+ log_error_errno(r, "Failed to remove subvolume: %m");
+
+ r = btrfs_subvol_snapshot("/etc", "/etc2", true, true);
+ if (r < 0)
+ log_error_errno(r, "Failed to make snapshot: %m");
+
+ r = btrfs_subvol_remove("/etc2");
+ if (r < 0)
+ log_error_errno(r, "Failed to remove subvolume: %m");
+
+ return 0;
+}
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
index dfa9a063c2..632d62ff8f 100644
--- a/src/test/test-cap-list.c
+++ b/src/test/test-cap-list.c
@@ -19,17 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "util.h"
#include "log.h"
+#include "fileio.h"
#include "cap-list.h"
#include "capability.h"
+#include <sys/prctl.h>
-int main(int argc, char *argv[]) {
+/* verify the capability parser */
+static void test_cap_list(void) {
int i;
assert_se(!capability_to_name(-1));
- assert_se(!capability_to_name(cap_last_cap()+1));
+ assert_se(!capability_to_name(capability_list_length()));
- for (i = 0; i <= (int) cap_last_cap(); i++) {
+ for (i = 0; i < capability_list_length(); i++) {
const char *n;
assert_se(n = capability_to_name(i));
@@ -39,9 +43,69 @@ int main(int argc, char *argv[]) {
assert_se(capability_from_name("asdfbsd") == -EINVAL);
assert_se(capability_from_name("CAP_AUDIT_READ") == CAP_AUDIT_READ);
+ assert_se(capability_from_name("cap_audit_read") == CAP_AUDIT_READ);
+ assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ);
assert_se(capability_from_name("0") == 0);
assert_se(capability_from_name("15") == 15);
assert_se(capability_from_name("-1") == -EINVAL);
+ for (i = 0; i < capability_list_length(); i++) {
+ _cleanup_cap_free_charp_ char *a = NULL;
+ const char *b;
+ unsigned u;
+
+ assert_se(a = cap_to_name(i));
+
+ /* quit the loop as soon as libcap starts returning
+ * numeric ids, formatted as strings */
+ if (safe_atou(a, &u) >= 0)
+ break;
+
+ assert_se(b = capability_to_name(i));
+
+ printf("%s vs. %s\n", a, b);
+
+ assert_se(strcasecmp(a, b) == 0);
+ }
+}
+
+/* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */
+static void test_last_cap_file(void) {
+ _cleanup_free_ char *content = NULL;
+ unsigned long val = 0;
+ int r;
+
+ r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
+ assert_se(r >= 0);
+
+ r = safe_atolu(content, &val);
+ assert_se(r >= 0);
+ assert_se(val != 0);
+ assert_se(val == cap_last_cap());
+}
+
+/* verify cap_last_cap() against syscall probing */
+static void test_last_cap_probe(void) {
+ unsigned long p = (unsigned long)CAP_LAST_CAP;
+
+ if (prctl(PR_CAPBSET_READ, p) < 0) {
+ for (p--; p > 0; p --)
+ if (prctl(PR_CAPBSET_READ, p) >= 0)
+ break;
+ } else {
+ for (;; p++)
+ if (prctl(PR_CAPBSET_READ, p+1) < 0)
+ break;
+ }
+
+ assert_se(p != 0);
+ assert_se(p == cap_last_cap());
+}
+
+int main(int argc, char *argv[]) {
+ test_cap_list();
+ test_last_cap_file();
+ test_last_cap_probe();
+
return 0;
}
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index 58eb744277..67eeeb56b7 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -93,6 +93,7 @@ static void test_path_get_user_unit(void) {
check_p_g_u_u("/meh.service", -ENOENT, NULL);
check_p_g_u_u("/session-3.scope/_cpu.service", 0, "cpu.service");
check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "server.service");
+ check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "foobar@pie.service");
check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENOENT, NULL);
}
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 349c6470c3..88147c8e0a 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -23,8 +23,13 @@
#include "log.h"
#include "architecture.h"
#include "sd-id128.h"
+#include "selinux-util.h"
+#include "audit.h"
+#include "ima-util.h"
+#include "apparmor-util.h"
+#include "smack-util.h"
-static void test_condition_test_path_exists(void) {
+static void test_condition_test_path(void) {
Condition *condition;
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
@@ -82,6 +87,14 @@ static void test_condition_test_path_exists(void) {
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
assert_se(!condition_test(condition));
condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
}
static void test_condition_test_ac_power(void) {
@@ -179,16 +192,46 @@ static void test_condition_test_null(void) {
condition_free(condition);
}
+static void test_condition_test_security(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
+ assert_se(condition_test(condition) != mac_selinux_use());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ assert_se(condition_test(condition) == use_ima());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
+ assert_se(condition_test(condition) == mac_apparmor_use());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "smack", false, false);
+ assert_se(condition_test(condition) == mac_smack_use());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "audit", false, false);
+ assert_se(condition_test(condition) == use_audit());
+ condition_free(condition);
+}
+
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_condition_test_path_exists();
+ test_condition_test_path();
test_condition_test_ac_power();
test_condition_test_host();
test_condition_test_architecture();
test_condition_test_kernel_command_line();
test_condition_test_null();
+ test_condition_test_security();
return 0;
}
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 71cfc022dd..894c7f742f 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -59,12 +59,12 @@ static void test_conf_files_list(bool use_root) {
search_2 = "/dir2";
} else {
root_dir = NULL;
- search_1 = strappenda(tmp_dir, "/dir1");
- search_2 = strappenda(tmp_dir, "/dir2");
+ search_1 = strjoina(tmp_dir, "/dir1");
+ search_2 = strjoina(tmp_dir, "/dir2");
}
- expect_a = strappenda(tmp_dir, "/dir1/a.conf");
- expect_b = strappenda(tmp_dir, "/dir2/b.conf");
+ expect_a = strjoina(tmp_dir, "/dir1/a.conf");
+ expect_b = strjoina(tmp_dir, "/dir2/b.conf");
assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0);
strv_print(found_files);
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index d2cad08cb6..5c96f61005 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -44,7 +44,7 @@ static void test_copy_file(void) {
assert_se(write_string_file(fn, "foo bar bar bar foo") == 0);
- assert_se(copy_file(fn, fn_copy, 0, 0644) == 0);
+ assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
assert_se(streq(buf, "foo bar bar bar foo\n"));
@@ -67,8 +67,8 @@ static void test_copy_file_fd(void) {
assert_se(out_fd >= 0);
assert_se(write_string_file(in_fn, text) == 0);
- assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd) < 0);
- assert_se(copy_file_fd(in_fn, out_fd) >= 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(lseek(out_fd, SEEK_SET, 0) == 0);
assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
@@ -90,15 +90,15 @@ static void test_copy_tree(void) {
rm_rf_dangerous(original_dir, false, true, false);
STRV_FOREACH(p, files) {
- char *f = strappenda(original_dir, *p);
+ char *f = strjoina(original_dir, *p);
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file") == 0);
}
STRV_FOREACH_PAIR(link, p, links) {
- char *f = strappenda(original_dir, *p);
- char *l = strappenda(original_dir, *link);
+ char *f = strjoina(original_dir, *p);
+ char *l = strjoina(original_dir, *link);
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
@@ -109,7 +109,7 @@ static void test_copy_tree(void) {
STRV_FOREACH(p, files) {
_cleanup_free_ char *buf = NULL;
size_t sz = 0;
- char *f = strappenda(copy_dir, *p);
+ char *f = strjoina(copy_dir, *p);
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
@@ -118,8 +118,8 @@ static void test_copy_tree(void) {
STRV_FOREACH_PAIR(link, p, links) {
_cleanup_free_ char *target = NULL;
- char *f = strappenda(original_dir, *p);
- char *l = strappenda(copy_dir, *link);
+ char *f = strjoina(original_dir, *p);
+ char *l = strjoina(copy_dir, *link);
assert_se(readlink_and_canonicalize(l, &target) == 0);
assert_se(path_equal(f, target));
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 60466f0d3f..91ccaf72b8 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -132,6 +132,11 @@ static void test_exec_environment(Manager *m) {
test(m, "exec-environment-empty.service", 0, CLD_EXITED);
}
+static void test_exec_umask(Manager *m) {
+ test(m, "exec-umask-default.service", 0, CLD_EXITED);
+ test(m, "exec-umask-0177.service", 0, CLD_EXITED);
+}
+
int main(int argc, char *argv[]) {
test_function_t tests[] = {
test_exec_workingdirectory,
@@ -144,6 +149,7 @@ int main(int argc, char *argv[]) {
test_exec_user,
test_exec_group,
test_exec_environment,
+ test_exec_umask,
NULL,
};
test_function_t *test = NULL;
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index cdf1973ea5..63e4a19b76 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -90,7 +90,7 @@ static void test_parse_env_file(void) {
assert_se(streq_ptr(a[9], "ten="));
assert_se(a[10] == NULL);
- strv_env_clean_log(a, NULL, "test");
+ strv_env_clean(a);
k = 0;
STRV_FOREACH(i, b) {
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
new file mode 100644
index 0000000000..50e5dee0a7
--- /dev/null
+++ b/src/test/test-fstab-util.c
@@ -0,0 +1,138 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 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 "fstab-util.h"
+#include "util.h"
+#include "log.h"
+
+/*
+int fstab_filter_options(const char *opts, const char *names,
+ const char **namefound, char **value, char **filtered);
+*/
+
+static void do_fstab_filter_options(const char *opts,
+ const char *remove,
+ int r_expected,
+ const char *name_expected,
+ const char *value_expected,
+ const char *filtered_expected) {
+
+ int r;
+ const char *name;
+ _cleanup_free_ char *value, *filtered;
+
+ r = fstab_filter_options(opts, remove, &name, &value, &filtered);
+ log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"",
+ opts, r, name, value, filtered,
+ r_expected, name_expected, value_expected, filtered_expected ?: opts);
+ assert_se(r == r_expected);
+ assert_se(streq_ptr(name, name_expected));
+ assert_se(streq_ptr(value, value_expected));
+ assert_se(streq_ptr(filtered, filtered_expected ?: opts));
+
+ /* also test the malloc-less mode */
+ r = fstab_filter_options(opts, remove, &name, NULL, NULL);
+ log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"",
+ opts, r, name,
+ r_expected, name_expected);
+ assert_se(r == r_expected);
+ assert_se(streq_ptr(name, name_expected));
+}
+
+static void test_fstab_filter_options(void) {
+ do_fstab_filter_options("opt=0", "opt\0x-opt\0", 1, "opt", "0", "");
+ do_fstab_filter_options("opt=0", "x-opt\0opt\0", 1, "opt", "0", "");
+ do_fstab_filter_options("opt", "opt\0x-opt\0", 1, "opt", NULL, "");
+ do_fstab_filter_options("opt", "x-opt\0opt\0", 1, "opt", NULL, "");
+ do_fstab_filter_options("x-opt", "x-opt\0opt\0", 1, "x-opt", NULL, "");
+
+ do_fstab_filter_options("opt=0,other", "opt\0x-opt\0", 1, "opt", "0", "other");
+ do_fstab_filter_options("opt=0,other", "x-opt\0opt\0", 1, "opt", "0", "other");
+ do_fstab_filter_options("opt,other", "opt\0x-opt\0", 1, "opt", NULL, "other");
+ do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other");
+ do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other");
+
+ do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
+ do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
+ do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
+
+ do_fstab_filter_options("first,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first");
+ do_fstab_filter_options("first=1,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first=1");
+ do_fstab_filter_options("first,opt=", "opt\0x-opt\0", 1, "opt", "", "first");
+ do_fstab_filter_options("first=1,opt", "opt\0x-opt\0", 1, "opt", NULL, "first=1");
+ do_fstab_filter_options("first=1,x-opt", "opt\0x-opt\0", 1, "x-opt", NULL, "first=1");
+
+ do_fstab_filter_options("first,opt=0,last=1", "opt\0x-opt\0", 1, "opt", "0", "first,last=1");
+ do_fstab_filter_options("first=1,opt=0,last=2", "x-opt\0opt\0", 1, "opt", "0", "first=1,last=2");
+ do_fstab_filter_options("first,opt,last", "opt\0", 1, "opt", NULL, "first,last");
+ do_fstab_filter_options("first=1,opt,last", "x-opt\0opt\0", 1, "opt", NULL, "first=1,last");
+ do_fstab_filter_options("first=,opt,last", "opt\0noopt\0", 1, "opt", NULL, "first=,last");
+
+ /* check repeated options */
+ do_fstab_filter_options("first,opt=0,noopt=1,last=1", "opt\0noopt\0", 1, "noopt", "1", "first,last=1");
+ do_fstab_filter_options("first=1,opt=0,last=2,opt=1", "opt\0", 1, "opt", "1", "first=1,last=2");
+ do_fstab_filter_options("x-opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", "");
+ do_fstab_filter_options("opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", "");
+
+ /* check that semicolons are not misinterpreted */
+ do_fstab_filter_options("opt=0;", "opt\0", 1, "opt", "0;", "");
+ do_fstab_filter_options("opt;=0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL);
+ do_fstab_filter_options("opt;", "opt\0x-opt\0", 0, NULL, NULL, NULL);
+
+ /* check that spaces are not misinterpreted */
+ do_fstab_filter_options("opt=0 ", "opt\0", 1, "opt", "0 ", "");
+ do_fstab_filter_options("opt =0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL);
+ do_fstab_filter_options(" opt ", "opt\0x-opt\0", 0, NULL, NULL, NULL);
+
+ /* check function will NULL args */
+ do_fstab_filter_options(NULL, "opt\0", 0, NULL, NULL, "");
+ do_fstab_filter_options("", "opt\0", 0, NULL, NULL, "");
+}
+
+static void test_fstab_find_pri(void) {
+ int pri = -1;
+
+ assert_se(fstab_find_pri("pri", &pri) == 0);
+ assert_se(pri == -1);
+
+ assert_se(fstab_find_pri("pri=11", &pri) == 1);
+ assert_se(pri == 11);
+
+ assert_se(fstab_find_pri("opt,pri=12,opt", &pri) == 1);
+ assert_se(pri == 12);
+
+ assert_se(fstab_find_pri("opt,opt,pri=12,pri=13", &pri) == 1);
+ assert_se(pri == 13);
+}
+
+static void test_fstab_yes_no_option(void) {
+ assert_se(fstab_test_yes_no_option("nofail,fail,nofail", "nofail\0fail\0") == true);
+ assert_se(fstab_test_yes_no_option("nofail,nofail,fail", "nofail\0fail\0") == false);
+ assert_se(fstab_test_yes_no_option("abc,cde,afail", "nofail\0fail\0") == false);
+ assert_se(fstab_test_yes_no_option("nofail,fail=0,nofail=0", "nofail\0fail\0") == true);
+ assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false);
+}
+
+int main(void) {
+ test_fstab_filter_options();
+ test_fstab_find_pri();
+ test_fstab_yes_no_option();
+}
diff --git a/src/test/test-fw-util.c b/src/test/test-fw-util.c
new file mode 100644
index 0000000000..ab891aa0c4
--- /dev/null
+++ b/src/test/test-fw-util.c
@@ -0,0 +1,60 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Lennart Poettering
+
+ 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 "log.h"
+#include "fw-util.h"
+
+#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
+
+int main(int argc, char *argv[]) {
+ int r;
+ log_set_max_level(LOG_DEBUG);
+
+ r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_masquerade(false, AF_INET, 0, NULL, 0, "foobar", NULL, 0);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, &MAKE_IN_ADDR_UNION(1, 2, 3, 4));
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ r = fw_add_local_dnat(false, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, NULL);
+ if (r < 0)
+ log_error_errno(r, "Failed to modify firewall: %m");
+
+ return 0;
+}
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 6f0910aae7..84b508f874 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -245,6 +245,8 @@ static void test_hashmap_put(void) {
Hashmap *m = NULL;
int valid_hashmap_put;
void *val1 = (void*) "val 1";
+ void *val2 = (void*) "val 2";
+ _cleanup_free_ char* key1 = NULL;
assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0);
assert_se(m);
@@ -252,7 +254,10 @@ static void test_hashmap_put(void) {
valid_hashmap_put = hashmap_put(m, "key 1", val1);
assert_se(valid_hashmap_put == 1);
assert_se(hashmap_put(m, "key 1", val1) == 0);
- assert_se(hashmap_put(m, "key 1", (void *)"val 2") == -EEXIST);
+ assert_se(hashmap_put(m, "key 1", val2) == -EEXIST);
+ key1 = strdup("key 1");
+ assert_se(hashmap_put(m, key1, val1) == 0);
+ assert_se(hashmap_put(m, key1, val2) == -EEXIST);
hashmap_free(m);
}
diff --git a/src/test/test-json.c b/src/test/test-json.c
new file mode 100644
index 0000000000..b09131891c
--- /dev/null
+++ b/src/test/test-json.c
@@ -0,0 +1,107 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ 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 <math.h>
+
+#include "log.h"
+#include "util.h"
+#include "json.h"
+
+static void test_one(const char *data, ...) {
+ void *state = NULL;
+ va_list ap;
+
+ va_start(ap, data);
+
+ for (;;) {
+ _cleanup_free_ char *str = NULL;
+ union json_value v = {};
+ int t, tt;
+
+ t = json_tokenize(&data, &str, &v, &state, NULL);
+ tt = va_arg(ap, int);
+
+ assert_se(t == tt);
+
+ if (t == JSON_END || t < 0)
+ break;
+
+ else if (t == JSON_STRING) {
+ const char *nn;
+
+ nn = va_arg(ap, const char *);
+ assert_se(streq_ptr(nn, str));
+
+ } else if (t == JSON_REAL) {
+ double d;
+
+ d = va_arg(ap, double);
+ assert_se(fabs(d - v.real) < 0.001);
+
+ } else if (t == JSON_INTEGER) {
+ intmax_t i;
+
+ i = va_arg(ap, intmax_t);
+ assert_se(i == v.integer);
+
+ } else if (t == JSON_BOOLEAN) {
+ bool b;
+
+ b = va_arg(ap, int);
+ assert_se(b == v.boolean);
+ }
+ }
+
+ va_end(ap);
+}
+
+int main(int argc, char *argv[]) {
+
+ test_one("x", -EINVAL);
+ test_one("", JSON_END);
+ test_one(" ", JSON_END);
+ test_one("0", JSON_INTEGER, (intmax_t) 0, JSON_END);
+ test_one("1234", JSON_INTEGER, (intmax_t) 1234, JSON_END);
+ test_one("3.141", JSON_REAL, 3.141, JSON_END);
+ test_one("0.0", JSON_REAL, 0.0, JSON_END);
+ test_one("7e3", JSON_REAL, 7e3, JSON_END);
+ test_one("-7e-3", JSON_REAL, -7e-3, JSON_END);
+ test_one("true", JSON_BOOLEAN, true, JSON_END);
+ test_one("false", JSON_BOOLEAN, false, JSON_END);
+ test_one("null", JSON_NULL, JSON_END);
+ test_one("{}", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
+ test_one("\t {\n} \n", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
+ test_one("[]", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
+ test_one("\t [] \n\n", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
+ test_one("\"\"", JSON_STRING, "", JSON_END);
+ test_one("\"foo\"", JSON_STRING, "foo", JSON_END);
+ test_one("\"foo\\nfoo\"", JSON_STRING, "foo\nfoo", JSON_END);
+ test_one("{\"foo\" : \"bar\"}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_STRING, "bar", JSON_OBJECT_CLOSE, JSON_END);
+ test_one("{\"foo\" : [true, false]}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_ARRAY_OPEN, JSON_BOOLEAN, true, JSON_COMMA, JSON_BOOLEAN, false, JSON_ARRAY_CLOSE, JSON_OBJECT_CLOSE, JSON_END);
+ test_one("\"\xef\xbf\xbd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
+ test_one("\"\\ufffd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
+ test_one("\"\\uf\"", -EINVAL);
+ test_one("\"\\ud800a\"", -EINVAL);
+ test_one("\"\\udc00\\udc00\"", -EINVAL);
+ test_one("\"\\ud801\\udc37\"", JSON_STRING, "\xf0\x90\x90\xb7", JSON_END);
+
+ return 0;
+}
diff --git a/src/test/test-list.c b/src/test/test-list.c
index fa52ad1db8..f6da1a7053 100644
--- a/src/test/test-list.c
+++ b/src/test/test-list.c
@@ -38,6 +38,27 @@ int main(int argc, const char *argv[]) {
LIST_PREPEND(item, head, &items[i]);
}
+ i = 0;
+ LIST_FOREACH_OTHERS(item, cursor, &items[2]) {
+ i++;
+ assert_se(cursor != &items[2]);
+ }
+ assert_se(i == ELEMENTSOF(items)-1);
+
+ i = 0;
+ LIST_FOREACH_OTHERS(item, cursor, &items[0]) {
+ i++;
+ assert_se(cursor != &items[0]);
+ }
+ assert_se(i == ELEMENTSOF(items)-1);
+
+ i = 0;
+ LIST_FOREACH_OTHERS(item, cursor, &items[3]) {
+ i++;
+ assert_se(cursor != &items[3]);
+ }
+ assert_se(i == ELEMENTSOF(items)-1);
+
assert_se(!LIST_JUST_US(item, head));
assert_se(items[0].item_next == NULL);
@@ -105,5 +126,29 @@ int main(int argc, const char *argv[]) {
LIST_REMOVE(item, head, &items[3]);
assert_se(LIST_JUST_US(item, &items[3]));
+ assert_se(head == NULL);
+
+ for (i = 0; i < ELEMENTSOF(items); i++) {
+ assert_se(LIST_JUST_US(item, &items[i]));
+ LIST_APPEND(item, head, &items[i]);
+ }
+
+ assert_se(!LIST_JUST_US(item, head));
+
+ assert_se(items[0].item_next == &items[1]);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[2].item_next == &items[3]);
+ assert_se(items[3].item_next == NULL);
+
+ assert_se(items[0].item_prev == NULL);
+ assert_se(items[1].item_prev == &items[0]);
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[3].item_prev == &items[2]);
+
+ for (i = 0; i < ELEMENTSOF(items); i++)
+ LIST_REMOVE(item, head, &items[i]);
+
+ assert_se(head == NULL);
+
return 0;
}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index ab330ac840..75fe053b63 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -25,11 +25,15 @@
#include <fcntl.h>
#include "loopback-setup.h"
+#include "log.h"
#include "util.h"
int main(int argc, char* argv[]) {
int r;
+ log_open();
+ log_parse_environment();
+
if ((r = loopback_setup()) < 0)
fprintf(stderr, "loopback: %s\n", strerror(-r));
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index e74fd0c88a..2397db5fff 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -19,7 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <libgen.h>
#include <sys/socket.h>
#include "namespace.h"
@@ -43,8 +42,8 @@ static void test_tmpdir(const char *id, const char *A, const char *B) {
assert_se((x.st_mode & 01777) == 0700);
assert_se((y.st_mode & 01777) == 0700);
- c = strappenda(a, "/tmp");
- d = strappenda(b, "/tmp");
+ c = strjoina(a, "/tmp");
+ d = strjoina(b, "/tmp");
assert_se(stat(c, &x) >= 0);
assert_se(stat(d, &y) >= 0);
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
new file mode 100644
index 0000000000..38e5c93df6
--- /dev/null
+++ b/src/test/test-path-lookup.c
@@ -0,0 +1,74 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 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/stat.h>
+#include <sys/types.h>
+
+#include "path-lookup.h"
+#include "log.h"
+#include "strv.h"
+
+static void test_paths(SystemdRunningAs running_as, bool personal) {
+ char template[] = "/tmp/test-path-lookup.XXXXXXX";
+
+ _cleanup_lookup_paths_free_ LookupPaths lp = {};
+ char *exists, *not;
+
+ assert_se(mkdtemp(template));
+ exists = strjoina(template, "/exists");
+ assert_se(mkdir(exists, 0755) == 0);
+ not = strjoina(template, "/not");
+
+ assert_se(lookup_paths_init(&lp, running_as, personal, NULL, exists, not, not) == 0);
+
+ assert_se(!strv_isempty(lp.unit_path));
+ assert_se(strv_contains(lp.unit_path, exists));
+ assert_se(strv_contains(lp.unit_path, not));
+
+ assert_se(rm_rf_dangerous(template, false, true, false) >= 0);
+}
+
+static void print_generator_paths(SystemdRunningAs running_as) {
+ _cleanup_strv_free_ char **paths;
+ char **dir;
+
+ log_info("Generators dirs (%s):", running_as == SYSTEMD_SYSTEM ? "system" : "user");
+
+ paths = generator_paths(running_as);
+ STRV_FOREACH(dir, paths)
+ log_info(" %s", *dir);
+}
+
+int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_paths(SYSTEMD_SYSTEM, false);
+ test_paths(SYSTEMD_SYSTEM, true);
+ test_paths(SYSTEMD_USER, false);
+ test_paths(SYSTEMD_USER, true);
+
+ print_generator_paths(SYSTEMD_SYSTEM);
+ print_generator_paths(SYSTEMD_USER);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 58b456a291..11aa52aaed 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -176,13 +176,13 @@ static void test_path_join(void) {
test_join("/root", "/a/b", "/c", "/root/a/b/c");
test_join("/root", "a/b", "c", "/root/a/b/c");
test_join("/root", "/a/b", "c", "/root/a/b/c");
- test_join("/root", "/", "c", "/root//c");
+ test_join("/root", "/", "c", "/root/c");
test_join("/root", "/", NULL, "/root/");
test_join(NULL, "/a/b", "/c", "/a/b/c");
test_join(NULL, "a/b", "c", "a/b/c");
test_join(NULL, "/a/b", "c", "/a/b/c");
- test_join(NULL, "/", "c", "//c");
+ test_join(NULL, "/", "c", "/c");
test_join(NULL, "/", NULL, "/");
}
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 18fcb575e6..4f9f5c1344 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -47,7 +47,7 @@ static int setup_test(Manager **m) {
assert_se(manager_startup(tmp, NULL, NULL) >= 0);
STRV_FOREACH(test_path, tests_path) {
- rm_rf_dangerous(strappenda("/tmp/test-path_", *test_path), false, true, false);
+ rm_rf_dangerous(strjoina("/tmp/test-path_", *test_path), false, true, false);
}
*m = tmp;
@@ -81,7 +81,7 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
service = SERVICE(service_unit);
ts = now(CLOCK_MONOTONIC);
- /* We proces events until the service related to the path has been successfully started */
+ /* We process events until the service related to the path has been successfully started */
while(service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
usec_t n;
int r;
@@ -201,7 +201,7 @@ static void test_path_directorynotempty(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
assert_se(mkdir_p(test_path, 0755) >= 0);
- assert_se(touch(strappenda(test_path, "test_file")) >= 0);
+ assert_se(touch(strjoina(test_path, "test_file")) >= 0);
check_stop_unlink(m, unit, test_path, NULL);
}
@@ -248,10 +248,6 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- /* It is needed otherwise cgroup creation fails */
- if (getuid() != 0)
- return EXIT_TEST_SKIP;
-
assert_se(set_unit_path(TEST_DIR ":") >= 0);
for (test = tests; test && *test; test++) {
diff --git a/src/test/test-pty.c b/src/test/test-pty.c
index ed23e9f0f1..cab569a9da 100644
--- a/src/test/test-pty.c
+++ b/src/test/test-pty.c
@@ -100,7 +100,7 @@ static void test_pty(void) {
Pty *pty;
rcvsiz = 0;
- memset(rcvbuf, 0, sizeof(rcvbuf));
+ zero(rcvbuf);
assert_se(sd_event_default(&event) >= 0);
diff --git a/src/test/test-ring.c b/src/test/test-ring.c
index 5e4efdbde9..a9dd01ca01 100644
--- a/src/test/test-ring.c
+++ b/src/test/test-ring.c
@@ -36,7 +36,7 @@ static void test_ring(void) {
struct iovec vec[2];
int s;
- memset(&r, 0, sizeof(r));
+ zero(r);
l = ring_peek(&r, vec);
assert_se(l == 0);
diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c
new file mode 100644
index 0000000000..f5bae65bef
--- /dev/null
+++ b/src/test/test-sigbus.c
@@ -0,0 +1,62 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ 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/mman.h>
+
+#include "util.h"
+#include "sigbus.h"
+
+int main(int argc, char *argv[]) {
+ _cleanup_close_ int fd = -1;
+ char template[] = "/tmp/sigbus-test-XXXXXX";
+ void *addr = NULL;
+ uint8_t *p;
+
+ sigbus_install();
+
+ assert_se(sigbus_pop(&addr) == 0);
+
+ assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0);
+ assert_se(unlink(template) >= 0);
+ assert_se(fallocate(fd, 0, 0, page_size() * 8) >= 0);
+
+ p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ assert_se(p != MAP_FAILED);
+
+ assert_se(sigbus_pop(&addr) == 0);
+
+ p[0] = 0xFF;
+ assert_se(sigbus_pop(&addr) == 0);
+
+ p[page_size()] = 0xFF;
+ assert_se(sigbus_pop(&addr) == 0);
+
+ p[page_size()*8] = 0xFF;
+ p[page_size()*8+1] = 0xFF;
+ p[page_size()*10] = 0xFF;
+ assert_se(sigbus_pop(&addr) > 0);
+ assert_se(addr == p + page_size() * 8);
+ assert_se(sigbus_pop(&addr) > 0);
+ assert_se(addr == p + page_size() * 10);
+ assert_se(sigbus_pop(&addr) == 0);
+
+ sigbus_reset();
+}
diff --git a/src/test/test-strbuf.c b/src/test/test-strbuf.c
index 43cb92b74b..4ec648ae66 100644
--- a/src/test/test-strbuf.c
+++ b/src/test/test-strbuf.c
@@ -48,7 +48,7 @@ static void test_strbuf(void) {
/* check the content of the buffer directly */
l = strv_parse_nulstr(sb->buf, sb->len);
- assert_se(streq(l[0], "")); /* root*/
+ assert_se(streq(l[0], "")); /* root */
assert_se(streq(l[1], "waldo"));
assert_se(streq(l[2], "foo"));
assert_se(streq(l[3], "bar"));
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index 674c1b53fc..5ae929c3f8 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -175,7 +175,7 @@ static void test_strv_quote_unquote(const char* const *split, const char *quoted
}
}
-static void test_strv_unquote(const char *quoted, const char **list) {
+static void test_strv_unquote(const char *quoted, char **list) {
_cleanup_strv_free_ char **s;
_cleanup_free_ char *j;
unsigned i = 0;
@@ -470,6 +470,78 @@ static void test_strv_push(void) {
assert_se(streq_ptr(a[3], NULL));
}
+static void test_strv_equal(void) {
+ _cleanup_strv_free_ char **a = NULL;
+ _cleanup_strv_free_ char **b = NULL;
+ _cleanup_strv_free_ char **c = NULL;
+
+ a = strv_new("one", "two", "three", NULL);
+ assert_se(a);
+ b = strv_new("one", "two", "three", NULL);
+ assert_se(a);
+ c = strv_new("one", "two", "three", "four", NULL);
+ assert_se(a);
+
+ assert_se(strv_equal(a, a));
+ assert_se(strv_equal(a, b));
+ assert_se(strv_equal(NULL, NULL));
+
+ assert_se(!strv_equal(a, c));
+ assert_se(!strv_equal(b, c));
+ assert_se(!strv_equal(b, NULL));
+}
+
+static void test_strv_is_uniq(void) {
+ _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
+
+ a = strv_new(NULL, NULL);
+ assert_se(a);
+ assert_se(strv_is_uniq(a));
+
+ b = strv_new("foo", NULL);
+ assert_se(b);
+ assert_se(strv_is_uniq(b));
+
+ c = strv_new("foo", "bar", NULL);
+ assert_se(c);
+ assert_se(strv_is_uniq(c));
+
+ d = strv_new("foo", "bar", "waldo", "bar", "piep", NULL);
+ assert_se(d);
+ assert_se(!strv_is_uniq(d));
+}
+
+static void test_strv_reverse(void) {
+ _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
+
+ a = strv_new(NULL, NULL);
+ assert_se(a);
+
+ strv_reverse(a);
+ assert_se(strv_isempty(a));
+
+ b = strv_new("foo", NULL);
+ assert_se(b);
+ strv_reverse(b);
+ assert_se(streq_ptr(b[0], "foo"));
+ assert_se(streq_ptr(b[1], NULL));
+
+ c = strv_new("foo", "bar", NULL);
+ assert_se(c);
+ strv_reverse(c);
+ assert_se(streq_ptr(c[0], "bar"));
+ assert_se(streq_ptr(c[1], "foo"));
+ assert_se(streq_ptr(c[2], NULL));
+
+ d = strv_new("foo", "bar", "waldo", NULL);
+ assert_se(d);
+ strv_reverse(d);
+ assert_se(streq_ptr(d[0], "waldo"));
+ assert_se(streq_ptr(d[1], "bar"));
+ assert_se(streq_ptr(d[2], "foo"));
+ assert_se(streq_ptr(d[3], NULL));
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
test_strv_foreach();
@@ -486,18 +558,22 @@ int main(int argc, char *argv[]) {
test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
- test_strv_unquote(" foo=bar \"waldo\" zzz ", (const char*[]) { "foo=bar", "waldo", "zzz", NULL });
- test_strv_unquote("", (const char*[]) { NULL });
- test_strv_unquote(" ", (const char*[]) { NULL });
- test_strv_unquote(" ", (const char*[]) { NULL });
- test_strv_unquote(" x", (const char*[]) { "x", NULL });
- test_strv_unquote("x ", (const char*[]) { "x", NULL });
- test_strv_unquote(" x ", (const char*[]) { "x", NULL });
- test_strv_unquote(" \"x\" ", (const char*[]) { "x", NULL });
- test_strv_unquote(" 'x' ", (const char*[]) { "x", NULL });
- test_strv_unquote(" 'x\"' ", (const char*[]) { "x\"", NULL });
- test_strv_unquote(" \"x'\" ", (const char*[]) { "x'", NULL });
- test_strv_unquote("a '--b=c \"d e\"'", (const char*[]) { "a", "--b=c \"d e\"", NULL });
+ test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
+ test_strv_unquote("", STRV_MAKE_EMPTY);
+ test_strv_unquote(" ", STRV_MAKE_EMPTY);
+ test_strv_unquote(" ", STRV_MAKE_EMPTY);
+ test_strv_unquote(" x", STRV_MAKE("x"));
+ test_strv_unquote("x ", STRV_MAKE("x"));
+ test_strv_unquote(" x ", STRV_MAKE("x"));
+ test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
+ test_strv_unquote(" 'x' ", STRV_MAKE("x"));
+ test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
+ test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
+ test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
+
+ /* trailing backslashes */
+ test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
+ test_invalid_unquote(" x\\");
test_invalid_unquote("a --b='c \"d e\"''");
test_invalid_unquote("a --b='c \"d e\" '\"");
@@ -519,6 +595,9 @@ int main(int argc, char *argv[]) {
test_strv_from_stdarg_alloca();
test_strv_push_prepend();
test_strv_push();
+ test_strv_equal();
+ test_strv_is_uniq();
+ test_strv_reverse();
return 0;
}
diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c
index cb2309210f..a7c8e1267d 100644
--- a/src/test/test-strxcpyx.c
+++ b/src/test/test-strxcpyx.c
@@ -48,7 +48,7 @@ static void test_strpcpyf(void) {
size_t space_left;
space_left = sizeof(target);
- space_left = strpcpyf(&s, space_left, "space left: %zd. ", space_left);
+ space_left = strpcpyf(&s, space_left, "space left: %zu. ", space_left);
space_left = strpcpyf(&s, space_left, "foo%s", "bar");
assert_se(streq(target, "space left: 25. foobar"));
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 97d5609adf..bda224bec6 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -46,7 +46,8 @@
#include "util.h"
#include "architecture.h"
#include "link-config.h"
-#include "bus-policy.h"
+#include "bus-xml-policy.h"
+#include "busname.h"
#include "journald-server.h"
#include "locale-util.h"
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 84050c6fa4..4b72c4a8fa 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -30,7 +30,7 @@
int main(int argc, char** argv) {
const char *p = argv[1] ?: "/tmp";
- char *pattern = strappenda(p, "/systemd-test-XXXXXX");
+ char *pattern = strjoina(p, "/systemd-test-XXXXXX");
_cleanup_close_ int fd, fd2;
_cleanup_free_ char *cmd, *cmd2;
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index f2283ec7a7..b57d275efa 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -32,6 +32,7 @@
#include <sys/signalfd.h>
#include "missing.h"
+#include "selinux-util.h"
#include "udev.h"
#include "udev-util.h"
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index f31a1bbc9b..e517f571d6 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -71,89 +71,117 @@ static void check_execcommand(ExecCommand *c,
const char* path,
const char* argv0,
const char* argv1,
+ const char* argv2,
bool ignore) {
+ size_t n;
+
assert_se(c);
- log_info("%s %s %s %s",
- c->path, c->argv[0], c->argv[1], c->argv[2]);
+ log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
+ path, argv0 ?: path, argv1, argv2);
+ n = strv_length(c->argv);
+ log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
+ c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
assert_se(streq(c->path, path));
- assert_se(streq(c->argv[0], argv0));
- assert_se(streq(c->argv[1], argv1));
- assert_se(c->argv[2] == NULL);
+ assert_se(streq(c->argv[0], argv0 ?: path));
+ if (n > 0)
+ assert_se(streq_ptr(c->argv[1], argv1));
+ if (n > 1)
+ assert_se(streq_ptr(c->argv[2], argv2));
assert_se(c->ignore == ignore);
}
static void test_config_parse_exec(void) {
- /* int config_parse_exec( */
- /* const char *filename, */
- /* unsigned line, */
- /* const char *section, */
- /* unsigned section_line, */
- /* const char *lvalue, */
- /* int ltype, */
- /* const char *rvalue, */
- /* void *data, */
- /* void *userdata) */
+ /* int config_parse_exec(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
int r;
ExecCommand *c = NULL, *c1;
+ const char *ccc;
- /* basic test */
+ log_info("/* basic test */");
r = config_parse_exec(NULL, "fake", 1, "section", 1,
"LValue", 0, "/RValue r1",
&c, NULL);
assert_se(r >= 0);
- check_execcommand(c, "/RValue", "/RValue", "r1", false);
+ check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
r = config_parse_exec(NULL, "fake", 2, "section", 1,
- "LValue", 0, "/RValue///slashes/// r1",
+ "LValue", 0, "/RValue///slashes r1///",
&c, NULL);
- /* test slashes */
+
+ log_info("/* test slashes */");
assert_se(r >= 0);
c1 = c->command_next;
- check_execcommand(c1, "/RValue/slashes", "/RValue///slashes///",
- "r1", false);
+ check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
- /* honour_argv0 */
+ log_info("/* trailing slash */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/RValue/ argv0 r1",
+ &c, NULL);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* honour_argv0 */");
r = config_parse_exec(NULL, "fake", 3, "section", 1,
- "LValue", 0, "@/RValue///slashes2/// argv0 r1",
+ "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
- check_execcommand(c1, "/RValue/slashes2", "argv0", "r1", false);
+ check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
+
+ log_info("/* honour_argv0, no args */");
+ r = config_parse_exec(NULL, "fake", 3, "section", 1,
+ "LValue", 0, "@/RValue",
+ &c, NULL);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
- /* ignore && honour_argv0 */
+ log_info("/* no command, check for bad memory access */");
+ r = config_parse_exec(NULL, "fake", 3, "section", 1,
+ "LValue", 0, " ",
+ &c, NULL);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* ignore && honour_argv0 */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "-@/RValue///slashes3/// argv0a r1",
+ "LValue", 0, "-@/RValue///slashes3 argv0a r1",
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
- check_execcommand(c1,
- "/RValue/slashes3", "argv0a", "r1", true);
+ check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
- /* ignore && honour_argv0 */
+ log_info("/* ignore && honour_argv0 */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "@-/RValue///slashes4/// argv0b r1",
+ "LValue", 0, "@-/RValue///slashes4 argv0b r1",
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
- check_execcommand(c1,
- "/RValue/slashes4", "argv0b", "r1", true);
+ check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
- /* ignore && ignore */
+ log_info("/* ignore && ignore */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "--/RValue argv0 r1",
&c, NULL);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
- /* ignore && ignore */
+ log_info("/* ignore && ignore (2) */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "-@-/RValue argv0 r1",
&c, NULL);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
- /* semicolon */
+ log_info("/* semicolon */");
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ; "
@@ -161,34 +189,119 @@ static void test_config_parse_exec(void) {
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ c1 = c1->command_next;
+ check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
+
+ log_info("/* trailing semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ; ",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* escaped semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/bin/find \\;",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+
+ log_info("/* escaped semicolon with following arg */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/sbin/find \\; x",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
check_execcommand(c1,
- "/RValue", "argv0", "r1", true);
+ "/sbin/find", NULL, ";", "x", false);
+ log_info("/* spaces in the filename */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH WITH SPACES/daemon\" -1 -2",
+ &c, NULL);
+ assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
- "/goo/goo", "/goo/goo", "boo", false);
+ "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
- /* trailing semicolon */
+ log_info("/* spaces in the filename, no args */");
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
- "-@/RValue argv0 r1 ; ",
+ "\"/PATH WITH SPACES/daemon -1 -2\"",
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
- "/RValue", "argv0", "r1", true);
+ "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
- assert_se(c1->command_next == NULL);
+ log_info("/* spaces in the filename, everything quoted */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
- /* escaped semicolon */
+ log_info("/* escaped spaces in the filename */");
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
- "/usr/bin/find \\;",
+ "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
&c, NULL);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
- "/usr/bin/find", "/usr/bin/find", ";", false);
+ "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
+
+ log_info("/* escaped spaces in the filename (2) */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
+
+ for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
+ /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
+ char path[] = "/path\\X";
+ path[sizeof(path) - 2] = *ccc;
+
+ log_info("/* invalid character: \\%c */", *ccc);
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, path,
+ &c, NULL);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+ }
+
+ log_info("/* valid character: \\s */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path\\s",
+ &c, NULL);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
+
+ log_info("/* trailing backslash: \\ */");
+ /* backslash is invalid */
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path\\",
+ &c, NULL);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
exec_command_free_list(c);
}
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index ab6c488cff..5c7f8b40f7 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -159,6 +159,7 @@ static int test_unit_printf(void) {
/* normal unit */
expect(u, "%n", "blah.service");
+ expect(u, "%f", "/blah");
expect(u, "%N", "blah");
expect(u, "%p", "blah");
expect(u, "%P", "blah");
@@ -178,6 +179,7 @@ static int test_unit_printf(void) {
expect(u2, "%n", "blah@foo-foo.service");
expect(u2, "%N", "blah@foo-foo");
+ expect(u2, "%f", "/foo/foo");
expect(u2, "%p", "blah");
expect(u2, "%P", "blah");
expect(u2, "%i", "foo-foo");
@@ -191,6 +193,7 @@ static int test_unit_printf(void) {
expect(u2, "%t", "/run/user/*");
manager_free(m);
+#undef expect
return 0;
}
@@ -260,6 +263,7 @@ static void test_unit_name_is_instance(void) {
assert_se(unit_name_is_instance("a-c_c01Aj@b05Dii_-oioi.service"));
assert_se(!unit_name_is_instance("a.service"));
+ assert_se(!unit_name_is_instance("a@.service"));
assert_se(!unit_name_is_instance("junk"));
assert_se(!unit_name_is_instance(""));
}
@@ -291,6 +295,11 @@ static void test_unit_name_to_instance(void) {
assert_se(streq(instance, "bar"));
free(instance);
+ r = unit_name_to_instance("foo@.service", &instance);
+ assert_se(r >= 0);
+ assert_se(streq(instance, ""));
+ free(instance);
+
r = unit_name_to_instance("fo0-stUff_b@b.e", &instance);
assert_se(r >= 0);
assert_se(streq(instance, "b"));
@@ -302,6 +311,9 @@ static void test_unit_name_to_instance(void) {
r = unit_name_to_instance("fooj@unk", &instance);
assert_se(r < 0);
+
+ r = unit_name_to_instance("foo@", &instance);
+ assert_se(r < 0);
}
static void test_unit_name_escape(void) {
@@ -312,6 +324,29 @@ static void test_unit_name_escape(void) {
assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
}
+static void test_unit_name_template(void) {
+#define expect(name, expected) \
+ { \
+ _cleanup_free_ char *f = NULL; \
+ f = unit_name_template(name); \
+ assert_se(f); \
+ printf("got: %s, expected: %s\n", f, expected); \
+ assert_se(streq(f, expected)); \
+ }
+ expect("foo@bar.service", "foo@.service")
+ expect("foo.mount", "foo.mount")
+#undef expect
+}
+
+static void test_unit_name_is_template(void) {
+ assert_se(unit_name_is_template("foo@.service"));
+ assert_se(unit_name_is_template("bar@.path"));
+
+ assert_se(!unit_name_is_template("bar@i.mount"));
+ assert_se(!unit_name_is_template("bar@foobbbb.service"));
+ assert_se(!unit_name_is_template("barfoo.service"));
+}
+
int main(int argc, char* argv[]) {
int rc = 0;
test_replacements();
@@ -324,6 +359,8 @@ int main(int argc, char* argv[]) {
test_build_subslice();
test_unit_name_to_instance();
test_unit_name_escape();
+ test_unit_name_template();
+ test_unit_name_is_template();
return rc;
}
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index 3399f2ba9c..befa385754 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -93,6 +93,18 @@ static void test_utf8_escaping_printable(void) {
assert_se(utf8_is_valid(p6));
}
+static void test_utf16_to_utf8(void) {
+ char *a = NULL;
+ const uint16_t utf16[] = { 'a', 0xd800, 'b', 0xdc00, 'c', 0xd801, 0xdc37 };
+ const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7, 0 };
+
+ a = utf16_to_utf8(utf16, 14);
+ assert_se(a);
+ assert_se(streq(a, utf8));
+
+ free(a);
+}
+
int main(int argc, char *argv[]) {
test_utf8_is_valid();
test_utf8_is_printable();
@@ -100,6 +112,7 @@ int main(int argc, char *argv[]) {
test_utf8_encoded_valid_unichar();
test_utf8_escaping();
test_utf8_escaping_printable();
+ test_utf16_to_utf8();
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index fe54586eee..9515a8cbf1 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -145,6 +145,39 @@ static void test_alloca(void) {
assert_se(!memcmp(t, zero, 997));
}
+static void test_div_round_up(void) {
+ int div;
+
+ /* basic tests */
+ assert_se(DIV_ROUND_UP(0, 8) == 0);
+ assert_se(DIV_ROUND_UP(1, 8) == 1);
+ assert_se(DIV_ROUND_UP(8, 8) == 1);
+ assert_se(DIV_ROUND_UP(12, 8) == 2);
+ assert_se(DIV_ROUND_UP(16, 8) == 2);
+
+ /* test multiple evaluation */
+ div = 0;
+ assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
+ assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
+ assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
+ assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
+
+ /* overflow test with exact division */
+ assert_se(sizeof(0U) == 4);
+ assert_se(0xfffffffaU % 10U == 0U);
+ assert_se(0xfffffffaU / 10U == 429496729U);
+ assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
+ assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
+ assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
+
+ /* overflow test with rounded division */
+ assert_se(0xfffffffdU % 10U == 3U);
+ assert_se(0xfffffffdU / 10U == 429496729U);
+ assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
+ assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
+ assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
+}
+
static void test_first_word(void) {
assert_se(first_word("Hello", ""));
assert_se(first_word("Hello", "Hello"));
@@ -383,8 +416,24 @@ static void test_cescape(void) {
static void test_cunescape(void) {
_cleanup_free_ char *unescaped;
- assert_se(unescaped = cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00"));
- assert_se(streq(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+ unescaped = cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00");
+ assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+
+ /* incomplete sequences */
+ unescaped = cunescape("\\x0");
+ assert_se(streq_ptr(unescaped, "\\x0"));
+
+ unescaped = cunescape("\\x");
+ assert_se(streq_ptr(unescaped, "\\x"));
+
+ unescaped = cunescape("\\");
+ assert_se(streq_ptr(unescaped, "\\"));
+
+ unescaped = cunescape("\\11");
+ assert_se(streq_ptr(unescaped, "\\11"));
+
+ unescaped = cunescape("\\1");
+ assert_se(streq_ptr(unescaped, "\\1"));
}
static void test_foreach_word(void) {
@@ -406,28 +455,12 @@ static void test_foreach_word(void) {
assert_se(strneq(expected[i++], word, l));
}
-static void test_foreach_word_quoted(void) {
+static void check(const char *test, char** expected, bool trailing) {
const char *word, *state;
size_t l;
int i = 0;
- const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
- const char * const expected[] = {
- "test",
- "a",
- "b",
- "c",
- "d",
- "e",
- "",
- "",
- "hhh",
- "",
- "",
- "a b c",
- NULL
- };
- printf("<%s>\n", test);
+ printf("<<<%s>>>\n", test);
FOREACH_WORD_QUOTED(word, l, test, state) {
_cleanup_free_ char *t = NULL;
@@ -435,7 +468,34 @@ static void test_foreach_word_quoted(void) {
assert_se(strneq(expected[i++], word, l));
printf("<%s>\n", t);
}
- assert_se(isempty(state));
+ printf("<<<%s>>>\n", state);
+ assert_se(expected[i] == NULL);
+ assert_se(isempty(state) == !trailing);
+}
+
+static void test_foreach_word_quoted(void) {
+ check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
+ STRV_MAKE("test",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "",
+ "",
+ "hhh",
+ "",
+ "",
+ "a b c"),
+ false);
+
+ check("test \"xxx",
+ STRV_MAKE("test"),
+ true);
+
+ check("test\\",
+ STRV_MAKE_EMPTY,
+ true);
}
static void test_default_term_for_tty(void) {
@@ -543,7 +603,7 @@ static void test_get_process_comm(void) {
r = get_process_environ(me, &env);
assert_se(r >= 0 || r == -EACCES);
- log_info("self strlen(environ): '%zd'", strlen(env));
+ log_info("self strlen(environ): '%zu'", strlen(env));
if (!detect_container(NULL))
assert_se(get_ctty_devnr(1, &h) == -ENOENT);
@@ -802,24 +862,24 @@ static void test_foreach_string(void) {
assert_se(streq(x, "zzz"));
}
-static void test_filename_is_safe(void) {
+static void test_filename_is_valid(void) {
char foo[FILENAME_MAX+2];
int i;
- assert_se(!filename_is_safe(""));
- assert_se(!filename_is_safe("/bar/foo"));
- assert_se(!filename_is_safe("/"));
- assert_se(!filename_is_safe("."));
- assert_se(!filename_is_safe(".."));
+ assert_se(!filename_is_valid(""));
+ assert_se(!filename_is_valid("/bar/foo"));
+ assert_se(!filename_is_valid("/"));
+ assert_se(!filename_is_valid("."));
+ assert_se(!filename_is_valid(".."));
for (i=0; i<FILENAME_MAX+1; i++)
foo[i] = 'a';
foo[FILENAME_MAX+1] = '\0';
- assert_se(!filename_is_safe(foo));
+ assert_se(!filename_is_valid(foo));
- assert_se(filename_is_safe("foo_bar-333"));
- assert_se(filename_is_safe("o.o"));
+ assert_se(filename_is_valid("foo_bar-333"));
+ assert_se(filename_is_valid("o.o"));
}
static void test_string_has_cc(void) {
@@ -858,15 +918,15 @@ static void test_files_same(void) {
}
static void test_is_valid_documentation_url(void) {
- assert_se(is_valid_documentation_url("http://www.freedesktop.org/wiki/Software/systemd"));
- assert_se(is_valid_documentation_url("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
- assert_se(is_valid_documentation_url("file:foo"));
- assert_se(is_valid_documentation_url("man:systemd.special(7)"));
- assert_se(is_valid_documentation_url("info:bar"));
+ assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
+ assert_se(documentation_url_is_valid("file:/foo/foo"));
+ assert_se(documentation_url_is_valid("man:systemd.special(7)"));
+ assert_se(documentation_url_is_valid("info:bar"));
- assert_se(!is_valid_documentation_url("foo:"));
- assert_se(!is_valid_documentation_url("info:"));
- assert_se(!is_valid_documentation_url(""));
+ assert_se(!documentation_url_is_valid("foo:"));
+ assert_se(!documentation_url_is_valid("info:"));
+ assert_se(!documentation_url_is_valid(""));
}
static void test_file_in_same_dir(void) {
@@ -1012,17 +1072,29 @@ static void test_strshorten(void) {
assert_se(strlen(strshorten(s, 0)) == 0);
}
-static void test_strappenda(void) {
+static void test_strjoina(void) {
char *actual;
- actual = strappenda("", "foo", "bar");
+ actual = strjoina("", "foo", "bar");
assert_se(streq(actual, "foobar"));
- actual = strappenda("foo", "bar", "baz");
+ actual = strjoina("foo", "bar", "baz");
assert_se(streq(actual, "foobarbaz"));
- actual = strappenda("foo", "", "bar", "baz");
+ actual = strjoina("foo", "", "bar", "baz");
assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo");
+ assert_se(streq(actual, "foo"));
+
+ actual = strjoina(NULL);
+ assert_se(streq(actual, ""));
+
+ actual = strjoina(NULL, "foo");
+ assert_se(streq(actual, ""));
+
+ actual = strjoina("foo", NULL, "bar");
+ assert_se(streq(actual, "foo"));
}
static void test_is_symlink(void) {
@@ -1163,23 +1235,47 @@ static void test_glob_exists(void) {
}
static void test_execute_directory(void) {
- char name[] = "/tmp/test-execute_directory/script1";
- char name2[] = "/tmp/test-execute_directory/script2";
- char name3[] = "/tmp/test-execute_directory/useless";
- char tempdir[] = "/tmp/test-execute_directory/";
-
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
- assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch /tmp/test-execute_directory/it_works") == 0);
- assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch /tmp/test-execute_directory/it_works2") == 0);
+ 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") == 0);
+ assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2") == 0);
+ assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed") == 0);
+ assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0") == 0);
+ assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed") == 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_directory(tempdir, NULL, DEFAULT_TIMEOUT_USEC, NULL);
- assert_se(access("/tmp/test-execute_directory/it_works", F_OK) >= 0);
- assert_se(access("/tmp/test-execute_directory/it_works2", F_OK) >= 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);
- rm_rf_dangerous(tempdir, false, true, false);
+ assert_se(chdir(template_hi) == 0);
+ assert_se(access("it_works2", F_OK) >= 0);
+ assert_se(access("failed", F_OK) < 0);
+
+ rm_rf_dangerous(template_lo, false, true, false);
+ rm_rf_dangerous(template_hi, false, true, false);
}
static void test_unquote_first_word(void) {
@@ -1312,6 +1408,110 @@ static void test_parse_proc_cmdline(void) {
assert_se(parse_proc_cmdline(parse_item) >= 0);
}
+static void test_raw_clone(void) {
+ pid_t parent, pid, pid2;
+
+ parent = getpid();
+ log_info("before clone: getpid()→"PID_FMT, parent);
+ assert_se(raw_getpid() == parent);
+
+ pid = raw_clone(0, NULL);
+ assert_se(pid >= 0);
+
+ pid2 = raw_getpid();
+ log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
+ pid, getpid(), pid2);
+ if (pid == 0) {
+ assert_se(pid2 != parent);
+ _exit(EXIT_SUCCESS);
+ } else {
+ int status;
+
+ assert_se(pid2 == parent);
+ waitpid(pid, &status, __WCLONE);
+ assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
+ }
+}
+
+static void test_same_fd(void) {
+ _cleanup_close_pair_ int p[2] = { -1, -1 };
+ _cleanup_close_ int a = -1, b = -1, c = -1;
+
+ assert_se(pipe2(p, O_CLOEXEC) >= 0);
+ assert_se((a = dup(p[0])) >= 0);
+ assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
+ assert_se((c = dup(a)) >= 0);
+
+ assert_se(same_fd(p[0], p[0]) > 0);
+ assert_se(same_fd(p[1], p[1]) > 0);
+ assert_se(same_fd(a, a) > 0);
+ assert_se(same_fd(b, b) > 0);
+
+ assert_se(same_fd(a, p[0]) > 0);
+ assert_se(same_fd(p[0], a) > 0);
+ assert_se(same_fd(c, p[0]) > 0);
+ assert_se(same_fd(p[0], c) > 0);
+ assert_se(same_fd(a, c) > 0);
+ assert_se(same_fd(c, a) > 0);
+
+ assert_se(same_fd(p[0], p[1]) == 0);
+ assert_se(same_fd(p[1], p[0]) == 0);
+ assert_se(same_fd(p[0], b) == 0);
+ assert_se(same_fd(b, p[0]) == 0);
+ assert_se(same_fd(p[1], a) == 0);
+ assert_se(same_fd(a, p[1]) == 0);
+ assert_se(same_fd(p[1], b) == 0);
+ assert_se(same_fd(b, p[1]) == 0);
+
+ assert_se(same_fd(a, b) == 0);
+ assert_se(same_fd(b, a) == 0);
+}
+
+static void test_uid_ptr(void) {
+
+ assert_se(UID_TO_PTR(0) != NULL);
+ assert_se(UID_TO_PTR(1000) != NULL);
+
+ assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
+ assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
+}
+
+static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
+ char check[n];
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+ assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
+
+ assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
+ assert_se(ftruncate(fd, n) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(read(fd, check, n) == (ssize_t) n);
+
+ assert_se(memcmp(buffer, check, n) == 0);
+}
+
+static void test_sparse_write(void) {
+ const char test_a[] = "test";
+ const char test_b[] = "\0\0\0\0test\0\0\0\0";
+ const char test_c[] = "\0\0test\0\0\0\0";
+ const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
+ const char test_e[] = "test\0\0\0\0test";
+ _cleanup_close_ int fd = -1;
+ char fn[] = "/tmp/sparseXXXXXX";
+
+ fd = mkostemp(fn, O_CLOEXEC);
+ assert_se(fd >= 0);
+ unlink(fn);
+
+ test_sparse_write_one(fd, test_a, sizeof(test_a));
+ test_sparse_write_one(fd, test_b, sizeof(test_b));
+ test_sparse_write_one(fd, test_c, sizeof(test_c));
+ test_sparse_write_one(fd, test_d, sizeof(test_d));
+ test_sparse_write_one(fd, test_e, sizeof(test_e));
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -1321,6 +1521,7 @@ int main(int argc, char *argv[]) {
test_max();
test_container_of();
test_alloca();
+ test_div_round_up();
test_first_word();
test_close_many();
test_parse_boolean();
@@ -1360,7 +1561,7 @@ int main(int argc, char *argv[]) {
test_hexdump();
test_log2i();
test_foreach_string();
- test_filename_is_safe();
+ test_filename_is_valid();
test_string_has_cc();
test_ascii_strlower();
test_files_same();
@@ -1373,7 +1574,7 @@ int main(int argc, char *argv[]) {
test_read_one_char();
test_ignore_signals();
test_strshorten();
- test_strappenda();
+ test_strjoina();
test_is_symlink();
test_pid_is_unwaited();
test_pid_is_alive();
@@ -1384,6 +1585,10 @@ int main(int argc, char *argv[]) {
test_unquote_first_word();
test_unquote_many_words();
test_parse_proc_cmdline();
+ test_raw_clone();
+ test_same_fd();
+ test_uid_ptr();
+ test_sparse_write();
return 0;
}
diff --git a/src/test/test-verbs.c b/src/test/test-verbs.c
new file mode 100644
index 0000000000..0fcdd9e78d
--- /dev/null
+++ b/src/test/test-verbs.c
@@ -0,0 +1,78 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2014 systemd developers
+
+ 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 "macro.h"
+#include "strv.h"
+#include "verbs.h"
+
+static int noop_dispatcher(int argc, char *argv[], void *userdata) {
+ return 0;
+}
+
+#define test_dispatch_one(argv, verbs, expected) \
+ optind = 0; \
+ assert_se(dispatch_verb(strv_length(argv), argv, verbs, NULL) == expected);
+
+static void test_verbs(void) {
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher },
+ { "list-images", VERB_ANY, 1, 0, noop_dispatcher },
+ { "list", VERB_ANY, 2, VERB_DEFAULT, noop_dispatcher },
+ { "status", 2, VERB_ANY, 0, noop_dispatcher },
+ { "show", VERB_ANY, VERB_ANY, 0, noop_dispatcher },
+ { "terminate", 2, VERB_ANY, 0, noop_dispatcher },
+ { "login", 2, 2, 0, noop_dispatcher },
+ { "copy-to", 3, 4, 0, noop_dispatcher },
+ {}
+ };
+
+ /* not found */
+ test_dispatch_one(STRV_MAKE("command-not-found"), verbs, -EINVAL);
+
+ /* found */
+ test_dispatch_one(STRV_MAKE("show"), verbs, 0);
+
+ /* found, too few args */
+ test_dispatch_one(STRV_MAKE("copy-to", "foo"), verbs, -EINVAL);
+
+ /* found, meets min args */
+ test_dispatch_one(STRV_MAKE("status", "foo", "bar"), verbs, 0);
+
+ /* found, too many args */
+ test_dispatch_one(STRV_MAKE("copy-to", "foo", "bar", "baz", "quux", "qaax"), verbs, -EINVAL);
+
+ /* no verb, but a default is set */
+ test_dispatch_one(STRV_MAKE_EMPTY, verbs, 0);
+}
+
+static void test_verbs_no_default(void) {
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher },
+ {},
+ };
+
+ test_dispatch_one(STRV_MAKE(NULL), verbs, -EINVAL);
+}
+
+int main(int argc, char *argv[]) {
+ test_verbs();
+ test_verbs_no_default();
+
+ return 0;
+}