summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/test-acl-util.c85
-rw-r--r--src/test/test-af-list.c49
-rw-r--r--src/test/test-alloc-util.c55
-rw-r--r--src/test/test-architecture.c14
-rw-r--r--src/test/test-arphrd-list.c49
-rw-r--r--src/test/test-ask-password-api.c38
-rw-r--r--src/test/test-async.c5
-rw-r--r--src/test/test-barrier.c2
-rw-r--r--src/test/test-bitmap.c20
-rw-r--r--src/test/test-boot-timestamps.c59
-rw-r--r--src/test/test-btrfs.c77
-rw-r--r--src/test/test-calendarspec.c98
-rw-r--r--src/test/test-cap-list.c13
-rw-r--r--src/test/test-capability.c82
-rw-r--r--src/test/test-cgroup-mask.c62
-rw-r--r--src/test/test-cgroup-util.c50
-rw-r--r--src/test/test-cgroup.c31
-rw-r--r--src/test/test-clock.c96
-rw-r--r--src/test/test-condition.c79
-rw-r--r--src/test/test-conf-files.c13
-rw-r--r--src/test/test-conf-parser.c14
-rw-r--r--src/test/test-copy.c112
-rw-r--r--src/test/test-cpu-set-util.c143
-rw-r--r--src/test/test-daemon.c29
-rw-r--r--src/test/test-date.c58
-rw-r--r--src/test/test-device-nodes.c4
-rw-r--r--src/test/test-dns-domain.c519
-rw-r--r--src/test/test-ellipsize.c8
-rw-r--r--src/test/test-engine.c40
-rw-r--r--src/test/test-env-util.c (renamed from src/test/test-env-replace.c)43
-rw-r--r--src/test/test-escape.c114
-rw-r--r--src/test/test-execute.c288
-rw-r--r--src/test/test-extract-word.c556
-rw-r--r--src/test/test-fd-util.c103
-rw-r--r--src/test/test-fdset.c20
-rw-r--r--src/test/test-fileio.c200
-rw-r--r--src/test/test-firewall-util.c4
-rw-r--r--src/test/test-fs-util.c243
-rw-r--r--src/test/test-fstab-util.c43
-rw-r--r--src/test/test-glob-util.c50
-rw-r--r--src/test/test-hashmap-plain.c25
-rw-r--r--src/test/test-hashmap.c2
-rw-r--r--src/test/test-helper.h14
-rw-r--r--src/test/test-hexdecoct.c387
-rw-r--r--src/test/test-hostname-util.c160
-rw-r--r--src/test/test-hostname.c2
-rw-r--r--src/test/test-id128.c91
-rw-r--r--src/test/test-install-root.c770
-rw-r--r--src/test/test-install.c119
-rw-r--r--src/test/test-io-util.c69
-rw-r--r--src/test/test-ipcrm.c16
-rw-r--r--src/test/test-job-type.c4
-rw-r--r--src/test/test-json.c202
-rw-r--r--src/test/test-libudev.c275
-rw-r--r--src/test/test-list.c67
-rw-r--r--src/test/test-locale-util.c2
-rw-r--r--src/test/test-log.c4
-rw-r--r--src/test/test-loopback.c13
-rw-r--r--src/test/test-namespace.c16
-rw-r--r--src/test/test-netlink-manual.c17
-rw-r--r--src/test/test-ns.c19
-rw-r--r--src/test/test-nss.c454
-rw-r--r--src/test/test-parse-util.c547
-rw-r--r--src/test/test-path-lookup.c50
-rw-r--r--src/test/test-path-util.c156
-rw-r--r--src/test/test-path.c33
-rw-r--r--src/test/test-prioq.c14
-rw-r--r--src/test/test-proc-cmdline.c63
-rw-r--r--src/test/test-process-util.c321
-rw-r--r--src/test/test-pty.c142
-rw-r--r--src/test/test-ratelimit.c11
-rw-r--r--src/test/test-replace-var.c5
-rw-r--r--src/test/test-ring.c130
-rw-r--r--src/test/test-rlimit-util.c116
-rw-r--r--src/test/test-sched-prio.c16
-rw-r--r--src/test/test-selinux.c122
-rw-r--r--src/test/test-sigbus.c8
-rw-r--r--src/test/test-signal-util.c67
-rw-r--r--src/test/test-siphash24.c124
-rw-r--r--src/test/test-sizeof.c53
-rw-r--r--src/test/test-sleep.c4
-rw-r--r--src/test/test-socket-util.c160
-rw-r--r--src/test/test-stat-util.c68
-rw-r--r--src/test/test-strbuf.c3
-rw-r--r--src/test/test-string-util.c370
-rw-r--r--src/test/test-strip-tab-ansi.c9
-rw-r--r--src/test/test-strv.c229
-rw-r--r--src/test/test-strxcpyx.c5
-rw-r--r--src/test/test-tables.c19
-rw-r--r--src/test/test-terminal-util.c10
-rw-r--r--src/test/test-time.c107
-rw-r--r--src/test/test-tmpfiles.c55
-rw-r--r--src/test/test-udev.c56
-rw-r--r--src/test/test-uid-range.c6
-rw-r--r--src/test/test-unaligned.c100
-rw-r--r--src/test/test-unit-file.c393
-rw-r--r--src/test/test-unit-name.c172
-rw-r--r--src/test/test-user-util.c166
-rw-r--r--src/test/test-utf8.c4
-rw-r--r--src/test/test-util.c1941
-rw-r--r--src/test/test-watchdog.c4
-rw-r--r--src/test/test-web-util.c39
-rw-r--r--src/test/test-xattr-util.c69
-rw-r--r--src/test/test-xml.c6
104 files changed, 8930 insertions, 3339 deletions
diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c
new file mode 100644
index 0000000000..5b572bb0bf
--- /dev/null
+++ b/src/test/test-acl-util.c
@@ -0,0 +1,85 @@
+/***
+ 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 <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "acl-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "string-util.h"
+#include "user-util.h"
+
+static void test_add_acls_for_user(void) {
+ char fn[] = "/tmp/test-empty.XXXXXX";
+ _cleanup_close_ int fd = -1;
+ char *cmd;
+ uid_t uid;
+ int r;
+
+ fd = mkostemp_safe(fn);
+ assert_se(fd >= 0);
+
+ /* Use the mode that user journal files use */
+ assert_se(fchmod(fd, 0640) == 0);
+
+ cmd = strjoina("ls -l ", fn);
+ assert_se(system(cmd) == 0);
+
+ cmd = strjoina("getfacl -p ", fn);
+ assert_se(system(cmd) == 0);
+
+ if (getuid() == 0) {
+ const char *nobody = "nobody";
+ r = get_user_creds(&nobody, &uid, NULL, NULL, NULL);
+ if (r < 0)
+ uid = 0;
+ } else
+ uid = getuid();
+
+ r = add_acls_for_user(fd, uid);
+ assert_se(r >= 0);
+
+ cmd = strjoina("ls -l ", fn);
+ assert_se(system(cmd) == 0);
+
+ cmd = strjoina("getfacl -p ", fn);
+ assert_se(system(cmd) == 0);
+
+ /* set the acls again */
+
+ r = add_acls_for_user(fd, uid);
+ assert_se(r >= 0);
+
+ cmd = strjoina("ls -l ", fn);
+ assert_se(system(cmd) == 0);
+
+ cmd = strjoina("getfacl -p ", fn);
+ assert_se(system(cmd) == 0);
+
+ unlink(fn);
+}
+
+int main(int argc, char **argv) {
+ test_add_acls_for_user();
+
+ return 0;
+}
diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c
new file mode 100644
index 0000000000..aeaa0929b1
--- /dev/null
+++ b/src/test/test-af-list.c
@@ -0,0 +1,49 @@
+/***
+ This file is part of systemd
+
+ Copyright 2015 Daniel Mack
+
+ 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 <string.h>
+#include <sys/socket.h>
+
+#include "macro.h"
+#include "string-util.h"
+#include "util.h"
+
+static const struct af_name* lookup_af(register const char *str, register unsigned int len);
+
+#include "af-from-name.h"
+#include "af-list.h"
+#include "af-to-name.h"
+
+int main(int argc, const char *argv[]) {
+
+ unsigned int i;
+
+ for (i = 0; i < ELEMENTSOF(af_names); i++) {
+ if (af_names[i]) {
+ assert_se(streq(af_to_name(i), af_names[i]));
+ assert_se(af_from_name(af_names[i]) == (int) i);
+ }
+ }
+
+ assert_se(af_to_name(af_max()) == NULL);
+ assert_se(af_to_name(-1) == NULL);
+ assert_se(af_from_name("huddlduddl") == AF_UNSPEC);
+
+ return 0;
+}
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
new file mode 100644
index 0000000000..cc4821eaf5
--- /dev/null
+++ b/src/test/test-alloc-util.c
@@ -0,0 +1,55 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "alloc-util.h"
+#include "macro.h"
+#include "util.h"
+
+static void test_alloca(void) {
+ static const uint8_t zero[997] = { };
+ char *t;
+
+ t = alloca_align(17, 512);
+ assert_se(!((uintptr_t)t & 0xff));
+ memzero(t, 17);
+
+ t = alloca0_align(997, 1024);
+ assert_se(!((uintptr_t)t & 0x1ff));
+ assert_se(!memcmp(t, zero, 997));
+}
+
+static void test_memdup_multiply(void) {
+ int org[] = {1, 2, 3};
+ int *dup;
+
+ dup = (int*)memdup_multiply(org, sizeof(int), 3);
+
+ assert_se(dup);
+ assert_se(dup[0] == 1);
+ assert_se(dup[1] == 2);
+ assert_se(dup[2] == 3);
+ free(dup);
+}
+
+int main(int argc, char *argv[]) {
+ test_alloca();
+ test_memdup_multiply();
+
+ return 0;
+}
diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c
index 30bdec45e5..f41e488d99 100644
--- a/src/test/test-architecture.c
+++ b/src/test/test-architecture.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,24 +17,24 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "virt.h"
#include "architecture.h"
-#include "util.h"
#include "log.h"
+#include "util.h"
+#include "virt.h"
int main(int argc, char *argv[]) {
- const char *id = NULL;
int a, v;
- v = detect_virtualization(&id);
+ v = detect_virtualization();
if (v == -EPERM || v == -EACCES)
return EXIT_TEST_SKIP;
assert_se(v >= 0);
log_info("virtualization=%s id=%s",
- v == VIRTUALIZATION_CONTAINER ? "container" : v == VIRTUALIZATION_VM ? "vm" : "n/a",
- strna(id));
+ VIRTUALIZATION_IS_CONTAINER(v) ? "container" :
+ VIRTUALIZATION_IS_VM(v) ? "vm" : "n/a",
+ virtualization_to_string(v));
a = uname_architecture();
assert_se(a >= 0);
diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c
new file mode 100644
index 0000000000..f3989ad201
--- /dev/null
+++ b/src/test/test-arphrd-list.c
@@ -0,0 +1,49 @@
+/***
+ This file is part of systemd
+
+ Copyright 2015 Daniel Mack
+
+ 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 <net/if_arp.h>
+#include <string.h>
+
+#include "macro.h"
+#include "string-util.h"
+#include "util.h"
+
+static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
+
+#include "arphrd-from-name.h"
+#include "arphrd-list.h"
+#include "arphrd-to-name.h"
+
+int main(int argc, const char *argv[]) {
+
+ unsigned int i;
+
+ for (i = 1; i < ELEMENTSOF(arphrd_names); i++) {
+ if (arphrd_names[i]) {
+ assert_se(streq(arphrd_to_name(i), arphrd_names[i]));
+ assert_se(arphrd_from_name(arphrd_names[i]) == (int) i);
+ }
+ }
+
+ assert_se(arphrd_to_name(arphrd_max()) == NULL);
+ assert_se(arphrd_to_name(0) == NULL);
+ assert_se(arphrd_from_name("huddlduddl") == 0);
+
+ return 0;
+}
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
new file mode 100644
index 0000000000..86666597c7
--- /dev/null
+++ b/src/test/test-ask-password-api.c
@@ -0,0 +1,38 @@
+/***
+ 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 "alloc-util.h"
+#include "ask-password-api.h"
+#include "log.h"
+
+static void ask_password(void) {
+ int r;
+ _cleanup_free_ char *ret;
+
+ r = ask_password_tty("hello?", "da key", 0, 0, NULL, &ret);
+ assert(r >= 0);
+
+ log_info("Got %s", ret);
+}
+
+int main(int argc, char **argv) {
+ log_parse_environment();
+
+ ask_password();
+}
diff --git a/src/test/test-async.c b/src/test/test-async.c
index abd36d693c..4ebc27f0bd 100644
--- a/src/test/test-async.c
+++ b/src/test/test-async.c
@@ -20,8 +20,9 @@
#include <unistd.h>
#include "async.h"
-#include "util.h"
+#include "fileio.h"
#include "macro.h"
+#include "util.h"
static bool test_async = false;
@@ -35,7 +36,7 @@ int main(int argc, char *argv[]) {
int fd;
char name[] = "/tmp/test-asynchronous_close.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
asynchronous_close(fd);
diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c
index f37cb49c85..e6aa3b5cfe 100644
--- a/src/test/test-barrier.c
+++ b/src/test/test-barrier.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
diff --git a/src/test/test-bitmap.c b/src/test/test-bitmap.c
index 96deeded7e..ff22117745 100644
--- a/src/test/test-bitmap.c
+++ b/src/test/test-bitmap.c
@@ -20,7 +20,7 @@
#include "bitmap.h"
int main(int argc, const char *argv[]) {
- _cleanup_bitmap_free_ Bitmap *b = NULL;
+ _cleanup_bitmap_free_ Bitmap *b = NULL, *b2 = NULL;
Iterator it;
unsigned n = (unsigned) -1, i = 0;
@@ -101,5 +101,23 @@ int main(int argc, const char *argv[]) {
assert_se(bitmap_set(b, (unsigned) -1) == -ERANGE);
+ bitmap_free(b);
+ b = NULL;
+ assert_se(bitmap_ensure_allocated(&b) == 0);
+ assert_se(bitmap_ensure_allocated(&b2) == 0);
+
+ assert_se(bitmap_equal(b, b2));
+ assert_se(bitmap_set(b, 0) == 0);
+ bitmap_unset(b, 0);
+ assert_se(bitmap_equal(b, b2));
+
+ assert_se(bitmap_set(b, 1) == 0);
+ bitmap_clear(b);
+ assert_se(bitmap_equal(b, b2));
+
+ assert_se(bitmap_set(b, 0) == 0);
+ assert_se(bitmap_set(b2, 0) == 0);
+ assert_se(bitmap_equal(b, b2));
+
return 0;
}
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index 06d93af533..8e68d6510d 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,11 +18,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "log.h"
+#include "acpi-fpdt.h"
#include "boot-timestamps.h"
#include "efivars.h"
-#include "acpi-fpdt.h"
+#include "log.h"
+#include "util.h"
static int test_acpi_fpdt(void) {
usec_t loader_start;
@@ -36,17 +34,18 @@ static int test_acpi_fpdt(void) {
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read ACPI FPDT: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA;
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read ACPI FPDT: %m");
+ return ok ? 0 : r;
}
log_info("ACPI FPDT: loader start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
static int test_efi_loader(void) {
@@ -59,33 +58,34 @@ static int test_efi_loader(void) {
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read EFI loader data: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read EFI loader data: %m");
+ return ok ? 0 : r;
}
log_info("EFI Loader: start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
-int main(int argc, char* argv[]) {
+static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
int r;
dual_timestamp fw, l, k;
- test_acpi_fpdt();
- test_efi_loader();
-
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
- log_error_errno(r, "Failed to read variables: %m");
- return 1;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read variables: %m");
+ return ok ? 0 : r;
}
log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
@@ -93,6 +93,21 @@ int main(int argc, char* argv[]) {
log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
+ return 1;
+}
+
+int main(int argc, char* argv[]) {
+ int p, q, r;
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ p = test_acpi_fpdt();
+ assert(p >= 0);
+ q = test_efi_loader();
+ assert(q >= 0);
+ r = test_boot_timestamps();
+ assert(r >= 0);
- return 0;
+ return (p > 0 || q > 0 || r >> 0) ? EXIT_SUCCESS : EXIT_TEST_SKIP;
}
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index e4771c9dd7..ce29d88412 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,23 +19,26 @@
#include <fcntl.h>
-#include "log.h"
+#include "btrfs-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "log.h"
+#include "parse-util.h"
+#include "string-util.h"
#include "util.h"
-#include "btrfs-util.h"
int main(int argc, char *argv[]) {
+ BtrfsQuotaInfo quota;
int r, 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];
+ BtrfsSubvolInfo info;
- r = btrfs_subvol_get_info_fd(fd, &info);
+ r = btrfs_subvol_get_info_fd(fd, 0, &info);
if (r < 0)
log_error_errno(r, "Failed to get subvolume info: %m");
else {
@@ -45,7 +46,7 @@ int main(int argc, char *argv[]) {
log_info("read-only (search): %s", yes_no(info.read_only));
}
- r = btrfs_subvol_get_quota_fd(fd, &quota);
+ r = btrfs_qgroup_get_quota_fd(fd, 0, &quota);
if (r < 0)
log_error_errno(r, "Failed to get quota info: %m");
else {
@@ -80,15 +81,15 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
- r = btrfs_subvol_remove("/xxxtest", false);
+ r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA);
if (r < 0)
log_error_errno(r, "Failed to remove subvolume: %m");
- r = btrfs_subvol_remove("/xxxtest2", false);
+ r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA);
if (r < 0)
log_error_errno(r, "Failed to remove subvolume: %m");
- r = btrfs_subvol_remove("/xxxtest3", false);
+ r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA);
if (r < 0)
log_error_errno(r, "Failed to remove subvolume: %m");
@@ -96,7 +97,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
- r = btrfs_subvol_remove("/etc2", false);
+ r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA);
if (r < 0)
log_error_errno(r, "Failed to remove subvolume: %m");
@@ -137,13 +138,61 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to snapshot subvolume: %m");
- r = btrfs_subvol_remove("/xxxrectest", true);
+ r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
if (r < 0)
log_error_errno(r, "Failed to recursively remove subvolume: %m");
- r = btrfs_subvol_remove("/xxxrectest2", true);
+ r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
if (r < 0)
log_error_errno(r, "Failed to recursively remove subvolume: %m");
+ r = btrfs_subvol_make("/xxxquotatest");
+ if (r < 0)
+ log_error_errno(r, "Failed to make subvolume: %m");
+
+ r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true);
+ if (r < 0)
+ log_error_errno(r, "Failed to set up auto qgroup: %m");
+
+ r = btrfs_subvol_make("/xxxquotatest/beneath");
+ if (r < 0)
+ log_error_errno(r, "Failed to make subvolume: %m");
+
+ r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false);
+ if (r < 0)
+ log_error_errno(r, "Failed to set up auto qgroup: %m");
+
+ r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024);
+ if (r < 0)
+ log_error_errno(r, "Failed to set up quota limit: %m");
+
+ r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024);
+ if (r < 0)
+ log_error_errno(r, "Failed to set up quota limit: %m");
+
+ r = btrfs_subvol_snapshot("/xxxquotatest", "/xxxquotatest2", BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA);
+ if (r < 0)
+ log_error_errno(r, "Failed to setup snapshot: %m");
+
+ r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, &quota);
+ if (r < 0)
+ log_error_errno(r, "Failed to query quota: %m");
+
+ assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024);
+
+ r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, &quota);
+ if (r < 0)
+ log_error_errno(r, "Failed to query quota: %m");
+
+ assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024);
+
+ r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
+ if (r < 0)
+ log_error_errno(r, "Failed remove subvolume: %m");
+
+ r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
+ if (r < 0)
+ log_error_errno(r, "Failed remove subvolume: %m");
+
return 0;
}
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 87e1da1258..57d9da4855 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,7 +19,9 @@
#include <string.h>
+#include "alloc-util.h"
#include "calendarspec.h"
+#include "string-util.h"
#include "util.h"
static void test_one(const char *input, const char *output) {
@@ -50,15 +50,77 @@ static void test_one(const char *input, const char *output) {
assert_se(streq(q, p));
}
+static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) {
+ CalendarSpec *c;
+ usec_t u;
+ char *old_tz;
+ char buf[FORMAT_TIMESTAMP_MAX];
+ int r;
+
+ old_tz = getenv("TZ");
+ if (old_tz)
+ old_tz = strdupa(old_tz);
+
+ if (new_tz)
+ assert_se(setenv("TZ", new_tz, 1) >= 0);
+ else
+ assert_se(unsetenv("TZ") >= 0);
+ tzset();
+
+ assert_se(calendar_spec_from_string(input, &c) >= 0);
+
+ printf("\"%s\"\n", input);
+
+ u = after;
+ r = calendar_spec_next_usec(c, after, &u);
+ printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u));
+ if (expect != (usec_t)-1)
+ assert_se(r >= 0 && u == expect);
+ else
+ assert(r == -ENOENT);
+
+ calendar_spec_free(c);
+
+ if (old_tz)
+ assert_se(setenv("TZ", old_tz, 1) >= 0);
+ else
+ assert_se(unsetenv("TZ") >= 0);
+ tzset();
+}
+
+static void test_timestamp(void) {
+ char buf[FORMAT_TIMESTAMP_MAX];
+ _cleanup_free_ char *t = NULL;
+ CalendarSpec *c;
+ usec_t x, y;
+
+ /* Ensure that a timestamp is also a valid calendar specification. Convert forth and back */
+
+ x = now(CLOCK_REALTIME);
+
+ assert_se(format_timestamp_us(buf, sizeof(buf), x));
+ printf("%s\n", buf);
+ assert_se(calendar_spec_from_string(buf, &c) >= 0);
+ assert_se(calendar_spec_to_string(c, &t) >= 0);
+ calendar_spec_free(c);
+ printf("%s\n", t);
+
+ assert_se(parse_timestamp(t, &y) >= 0);
+ assert_se(y == x);
+}
+
int main(int argc, char* argv[]) {
CalendarSpec *c;
- test_one("Sat,Thu,Mon-Wed,Sat-Sun", "Mon-Thu,Sat,Sun *-*-* 00:00:00");
+ test_one("Sat,Thu,Mon-Wed,Sat-Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00");
+ test_one("Sat,Thu,Mon..Wed,Sat..Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00");
test_one("Mon,Sun 12-*-* 2,1:23", "Mon,Sun 2012-*-* 01,02:23:00");
test_one("Wed *-1", "Wed *-*-01 00:00:00");
test_one("Wed-Wed,Wed *-1", "Wed *-*-01 00:00:00");
+ test_one("Wed..Wed,Wed *-1", "Wed *-*-01 00:00:00");
test_one("Wed, 17:48", "Wed *-*-* 17:48:00");
- test_one("Wed-Sat,Tue 12-10-15 1:2:3", "Tue-Sat 2012-10-15 01:02:03");
+ test_one("Wed-Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03");
+ test_one("Wed..Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03");
test_one("*-*-7 0:0:0", "*-*-07 00:00:00");
test_one("10-15", "*-10-15 00:00:00");
test_one("monday *-12-* 17:00", "Mon *-12-* 17:00:00");
@@ -82,11 +144,39 @@ int main(int argc, char* argv[]) {
test_one("semi-annually", "*-01,07-01 00:00:00");
test_one("annually", "*-01-01 00:00:00");
test_one("*:2/3", "*-*-* *:02/3:00");
+ test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC");
+ test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001");
+ test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
+ test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
+ test_one("9..11,13:00,30", "*-*-* 09,10,11,13:00,30:00");
+ test_one("1..3-1..3 1..3:1..3", "*-01,02,03-01,02,03 01,02,03:01,02,03:00");
+ test_one("00:00:1.125..2.125", "*-*-* 00:00:01.125000,02.125000");
+ test_one("00:00:1.0..3.8", "*-*-* 00:00:01,02,03");
+
+ test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
+ test_next("2016-03-27 03:17:00", "EET", 12345, -1);
+ test_next("2016-03-27 03:17:00 UTC", NULL, 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00.420000001 UTC", "EET", 12345, 1459048620420000);
+ test_next("2016-03-27 03:17:00.4200005 UTC", "EET", 12345, 1459048620420001);
+ test_next("2015-11-13 09:11:23.42", "EET", 12345, 1447398683420000);
+ test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000);
+ test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000);
+ test_next("Sun 16:00:00", "CET", 1456041600123456, 1456066800000000);
assert_se(calendar_spec_from_string("test", &c) < 0);
assert_se(calendar_spec_from_string("", &c) < 0);
assert_se(calendar_spec_from_string("7", &c) < 0);
assert_se(calendar_spec_from_string("121212:1:2", &c) < 0);
+ assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0);
+ assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0);
+ assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0);
+ assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0);
+
+ test_timestamp();
return 0;
}
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
index 43a2d35b80..4132ec56fd 100644
--- a/src/test/test-cap-list.c
+++ b/src/test/test-cap-list.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,12 +17,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "fileio.h"
-#include "cap-list.h"
-#include "capability.h"
#include <sys/prctl.h>
+#include "alloc-util.h"
+#include "cap-list.h"
+#include "capability-util.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "util.h"
+
/* verify the capability parser */
static void test_cap_list(void) {
int i;
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index f47452ce72..629bb63c81 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -17,20 +17,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/wait.h>
-#include <sys/capability.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <pwd.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
#include <unistd.h>
-#include "capability.h"
-#include "util.h"
+#include "capability-util.h"
+#include "fd-util.h"
#include "macro.h"
+#include "util.h"
static uid_t test_uid = -1;
static gid_t test_gid = -1;
-// We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage
+
+/* We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage */
static uint64_t test_flags = 1ULL << CAP_DAC_OVERRIDE;
static void fork_test(void (*test_func)(void)) {
@@ -64,8 +67,9 @@ static void show_capabilities(void) {
cap_free(text);
}
-static int setup_tests(void) {
+static int setup_tests(bool *run_ambient) {
struct passwd *nobody;
+ int r;
nobody = getpwnam("nobody");
if (!nobody) {
@@ -75,6 +79,18 @@ static int setup_tests(void) {
test_uid = nobody->pw_uid;
test_gid = nobody->pw_gid;
+ *run_ambient = false;
+
+ r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+
+ /* There's support for PR_CAP_AMBIENT if the prctl() call
+ * succeeded or error code was something else than EINVAL. The
+ * EINVAL check should be good enough to rule out false
+ * positives. */
+
+ if (r >= 0 || errno != EINVAL)
+ *run_ambient = true;
+
return 0;
}
@@ -138,8 +154,53 @@ static void test_have_effective_cap(void) {
assert_se(!have_effective_cap(CAP_CHOWN));
}
+static void test_update_inherited_set(void) {
+ cap_t caps;
+ uint64_t set = 0;
+ cap_flag_value_t fv;
+
+ caps = cap_get_proc();
+ assert_se(caps);
+ assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+ assert(fv == CAP_CLEAR);
+
+ set = (UINT64_C(1) << CAP_CHOWN);
+
+ assert_se(!capability_update_inherited_set(caps, set));
+ assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+ assert(fv == CAP_SET);
+
+ cap_free(caps);
+}
+
+static void test_set_ambient_caps(void) {
+ cap_t caps;
+ uint64_t set = 0;
+ cap_flag_value_t fv;
+
+ caps = cap_get_proc();
+ assert_se(caps);
+ assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+ assert(fv == CAP_CLEAR);
+ cap_free(caps);
+
+ assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0);
+
+ set = (UINT64_C(1) << CAP_CHOWN);
+
+ assert_se(!capability_ambient_set_apply(set, true));
+
+ caps = cap_get_proc();
+ assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+ assert(fv == CAP_SET);
+ cap_free(caps);
+
+ assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 1);
+}
+
int main(int argc, char *argv[]) {
int r;
+ bool run_ambient;
log_parse_environment();
log_open();
@@ -147,14 +208,19 @@ int main(int argc, char *argv[]) {
if (getuid() != 0)
return EXIT_TEST_SKIP;
- r = setup_tests();
+ r = setup_tests(&run_ambient);
if (r < 0)
return -r;
show_capabilities();
test_drop_privileges();
+ test_update_inherited_set();
+
fork_test(test_have_effective_cap);
+ if (run_ambient)
+ fork_test(test_set_ambient_caps);
+
return 0;
}
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index 72f874d8a9..a027eb0fd2 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,10 +19,12 @@
#include <stdio.h>
-#include "manager.h"
-#include "unit.h"
#include "macro.h"
+#include "manager.h"
+#include "rm-rf.h"
#include "test-helper.h"
+#include "tests.h"
+#include "unit.h"
static int test_cgroup_mask(void) {
Manager *m = NULL;
@@ -35,12 +35,24 @@ static int test_cgroup_mask(void) {
/* Prepare the manager. */
assert_se(set_unit_path(TEST_DIR) >= 0);
- r = manager_new(MANAGER_USER, true, &m);
+ r = manager_new(UNIT_FILE_USER, true, &m);
if (r == -EPERM || r == -EACCES) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
+
+ /* Turn off all kinds of default accouning, so that we can
+ * verify the masks resulting of our configuration and nothing
+ * else. */
+ m->default_cpu_accounting =
+ m->default_memory_accounting =
+ m->default_blockio_accounting =
+ m->default_io_accounting =
+ m->default_tasks_accounting = false;
+ m->default_tasks_max = (uint64_t) -1;
+
+ assert_se(r >= 0);
assert_se(manager_startup(m, serial, fdset) >= 0);
/* Load units and verify hierarchy. */
@@ -61,36 +73,36 @@ static int test_cgroup_mask(void) {
root = UNIT_DEREF(parent->slice);
/* Verify per-unit cgroups settings. */
- assert_se(unit_get_cgroup_mask(son) == (CGROUP_CPU | CGROUP_CPUACCT));
- assert_se(unit_get_cgroup_mask(daughter) == 0);
- assert_se(unit_get_cgroup_mask(grandchild) == 0);
- assert_se(unit_get_cgroup_mask(parent_deep) == CGROUP_MEMORY);
- assert_se(unit_get_cgroup_mask(parent) == CGROUP_BLKIO);
- assert_se(unit_get_cgroup_mask(root) == 0);
+ assert_se(unit_get_own_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT));
+ assert_se(unit_get_own_mask(daughter) == 0);
+ assert_se(unit_get_own_mask(grandchild) == 0);
+ assert_se(unit_get_own_mask(parent_deep) == CGROUP_MASK_MEMORY);
+ assert_se(unit_get_own_mask(parent) == (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
+ assert_se(unit_get_own_mask(root) == 0);
/* Verify aggregation of member masks */
assert_se(unit_get_members_mask(son) == 0);
assert_se(unit_get_members_mask(daughter) == 0);
assert_se(unit_get_members_mask(grandchild) == 0);
assert_se(unit_get_members_mask(parent_deep) == 0);
- assert_se(unit_get_members_mask(parent) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY));
- assert_se(unit_get_members_mask(root) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY));
+ assert_se(unit_get_members_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY));
+ assert_se(unit_get_members_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of sibling masks. */
- assert_se(unit_get_siblings_mask(son) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY));
- assert_se(unit_get_siblings_mask(daughter) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY));
+ assert_se(unit_get_siblings_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY));
+ assert_se(unit_get_siblings_mask(daughter) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY));
assert_se(unit_get_siblings_mask(grandchild) == 0);
- assert_se(unit_get_siblings_mask(parent_deep) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY));
- assert_se(unit_get_siblings_mask(parent) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY));
- assert_se(unit_get_siblings_mask(root) == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY));
+ assert_se(unit_get_siblings_mask(parent_deep) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY));
+ assert_se(unit_get_siblings_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
+ assert_se(unit_get_siblings_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of target masks. */
- assert_se(unit_get_target_mask(son) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported));
- assert_se(unit_get_target_mask(daughter) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported));
+ assert_se(unit_get_target_mask(son) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ assert_se(unit_get_target_mask(daughter) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported));
assert_se(unit_get_target_mask(grandchild) == 0);
- assert_se(unit_get_target_mask(parent_deep) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_MEMORY) & m->cgroup_supported));
- assert_se(unit_get_target_mask(parent) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY) & m->cgroup_supported));
- assert_se(unit_get_target_mask(root) == ((CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO | CGROUP_MEMORY) & m->cgroup_supported));
+ assert_se(unit_get_target_mask(parent_deep) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ assert_se(unit_get_target_mask(parent) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ assert_se(unit_get_target_mask(root) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
manager_free(m);
@@ -98,7 +110,11 @@ 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 ecc9d70bf4..c24c784e9b 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,12 +17,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
-#include "util.h"
+#include "alloc-util.h"
#include "cgroup-util.h"
-#include "test-helper.h"
+#include "dirent-util.h"
+#include "fd-util.h"
#include "formats-util.h"
+#include "parse-util.h"
#include "process-util.h"
+#include "stat-util.h"
+#include "string-util.h"
+#include "test-helper.h"
+#include "user-util.h"
+#include "util.h"
static void check_p_d_u(const char *path, int code, const char *result) {
_cleanup_free_ char *unit = NULL;
@@ -295,6 +299,39 @@ static void test_shift_path(void) {
test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo");
}
+static void test_mask_supported(void) {
+
+ CGroupMask m;
+ CGroupController c;
+
+ assert_se(cg_mask_supported(&m) >= 0);
+
+ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
+ printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
+}
+
+static void test_is_cgroup_fs(void) {
+ struct statfs sfs;
+ assert_se(statfs("/sys/fs/cgroup", &sfs) == 0);
+ if (is_temporary_fs(&sfs))
+ assert_se(statfs("/sys/fs/cgroup/systemd", &sfs) == 0);
+ assert_se(is_cgroup_fs(&sfs));
+}
+
+static void test_fd_is_cgroup_fs(void) {
+ int fd;
+
+ fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ assert_se(fd >= 0);
+ if (fd_is_temporary_fs(fd)) {
+ fd = safe_close(fd);
+ fd = open("/sys/fs/cgroup/systemd", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ assert_se(fd >= 0);
+ }
+ assert_se(fd_is_cgroup_fs(fd));
+ fd = safe_close(fd);
+}
+
int main(void) {
test_path_decode_unit();
test_path_get_unit();
@@ -309,6 +346,9 @@ int main(void) {
test_controller_is_valid();
test_slice_to_path();
test_shift_path();
+ TEST_REQ_RUNNING_SYSTEMD(test_mask_supported());
+ TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs());
+ TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs());
return 0;
}
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 4be69a408d..5336c19652 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,11 +17,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <string.h>
+#include <unistd.h>
#include "cgroup-util.h"
#include "path-util.h"
+#include "string-util.h"
#include "util.h"
int main(int argc, char*argv[]) {
@@ -56,26 +55,26 @@ int main(int argc, char*argv[]) {
assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
free(path);
- assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
- assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) == 0);
+ assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
+ assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
+ assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
+ assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
+ assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) == 0);
+ assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) > 0);
- assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0);
+ assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) > 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
+ assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
+ assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);
+ assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) > 0);
+ assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) == 0);
cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
- assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
- assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0);
+ assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
+ assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0);
assert_se(cg_split_spec("foobar:/", &c, &p) == 0);
assert_se(streq(c, "foobar"));
diff --git a/src/test/test-clock.c b/src/test/test-clock.c
new file mode 100644
index 0000000000..7d97328416
--- /dev/null
+++ b/src/test/test-clock.c
@@ -0,0 +1,96 @@
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2016 Canonical Ltd.
+
+ 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 <unistd.h>
+#include <fcntl.h>
+
+#include "clock-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "log.h"
+#include "macro.h"
+
+static void test_clock_is_localtime(void) {
+ char adjtime[] = "/tmp/test-adjtime.XXXXXX";
+ int fd = -1;
+ _cleanup_fclose_ FILE* f = NULL;
+
+ static const struct scenario {
+ const char* contents;
+ int expected_result;
+ } scenarios[] = {
+ /* adjtime configures UTC */
+ {"0.0 0 0\n0\nUTC\n", 0},
+ /* adjtime configures local time */
+ {"0.0 0 0\n0\nLOCAL\n", 1},
+ /* no final EOL */
+ {"0.0 0 0\n0\nUTC", 0},
+ {"0.0 0 0\n0\nLOCAL", 1},
+ /* empty value -> defaults to UTC */
+ {"0.0 0 0\n0\n", 0},
+ /* unknown value -> defaults to UTC */
+ {"0.0 0 0\n0\nFOO\n", 0},
+ /* no third line */
+ {"0.0 0 0", 0},
+ {"0.0 0 0\n", 0},
+ {"0.0 0 0\n0", 0},
+ };
+
+ /* without an adjtime file we default to UTC */
+ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0);
+
+ fd = mkostemp_safe(adjtime);
+ assert_se(fd >= 0);
+ log_info("adjtime test file: %s", adjtime);
+ f = fdopen(fd, "w");
+ assert_se(f);
+
+ for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) {
+ log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result);
+ log_info("%s", scenarios[i].contents);
+ rewind(f);
+ ftruncate(fd, 0);
+ assert_se(write_string_stream(f, scenarios[i].contents, false) == 0);
+ assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result);
+ }
+
+ unlink(adjtime);
+}
+
+/* Test with the real /etc/adjtime */
+static void test_clock_is_localtime_system(void) {
+ int r;
+ r = clock_is_localtime(NULL);
+
+ if (access("/etc/adjtime", F_OK) == 0) {
+ log_info("/etc/adjtime exists, clock_is_localtime() == %i", r);
+ /* if /etc/adjtime exists we expect some answer, no error or
+ * crash */
+ assert_se(r == 0 || r == 1);
+ } else
+ /* default is UTC if there is no /etc/adjtime */
+ assert_se(r == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_clock_is_localtime();
+ test_clock_is_localtime_system();
+
+ return 0;
+}
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index b788c9532d..6f7d71ef9a 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -17,83 +17,102 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "sd-id128.h"
+
+#include "alloc-util.h"
+#include "apparmor-util.h"
+#include "architecture.h"
+#include "audit-util.h"
#include "condition.h"
-#include "macro.h"
-#include "util.h"
+#include "hostname-util.h"
+#include "id128-util.h"
+#include "ima-util.h"
#include "log.h"
-#include "architecture.h"
-#include "sd-id128.h"
+#include "macro.h"
#include "selinux-util.h"
-#include "audit.h"
-#include "ima-util.h"
-#include "apparmor-util.h"
#include "smack-util.h"
-#include "hostname-util.h"
+#include "util.h"
static void test_condition_test_path(void) {
Condition *condition;
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
}
@@ -102,47 +121,59 @@ static void test_condition_test_ac_power(void) {
Condition *condition;
condition = condition_new(CONDITION_AC_POWER, "true", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) == on_ac_power());
condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) != on_ac_power());
condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, true);
+ assert_se(condition);
assert_se(condition_test(condition) == on_ac_power());
condition_free(condition);
}
static void test_condition_test_host(void) {
+ _cleanup_free_ char *hostname = NULL;
+ char sid[SD_ID128_STRING_MAX];
Condition *condition;
sd_id128_t id;
int r;
- char sid[SD_ID128_STRING_MAX];
- _cleanup_free_ char *hostname = NULL;
r = sd_id128_get_machine(&id);
assert_se(r >= 0);
assert_se(sd_id128_to_string(id, sid));
condition = condition_new(CONDITION_HOST, sid, false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_HOST, sid, false, true);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
hostname = gethostname_malloc();
assert_se(hostname);
- condition = condition_new(CONDITION_HOST, hostname, false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
+ /* if hostname looks like an id128 then skip testing it */
+ if (id128_is_valid(hostname))
+ log_notice("hostname is an id128, skipping test");
+ else {
+ condition = condition_new(CONDITION_HOST, hostname, false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+ }
}
static void test_condition_test_architecture(void) {
@@ -157,15 +188,18 @@ static void test_condition_test_architecture(void) {
assert_se(sa);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
- assert_se(condition_test(condition));
+ assert_se(condition);
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
- assert_se(condition_test(condition) < 0);
+ assert_se(condition);
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
- assert_se(!condition_test(condition));
+ assert_se(condition);
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
}
@@ -173,10 +207,12 @@ static void test_condition_test_kernel_command_line(void) {
Condition *condition;
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
}
@@ -185,10 +221,12 @@ static void test_condition_test_null(void) {
Condition *condition;
condition = condition_new(CONDITION_NULL, NULL, false, false);
+ assert_se(condition);
assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_NULL, NULL, false, true);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
}
@@ -197,31 +235,36 @@ static void test_condition_test_security(void) {
Condition *condition;
condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false);
+ assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
- assert_se(condition_test(condition) != mac_selinux_use());
+ assert_se(condition);
+ assert_se(condition_test(condition) != mac_selinux_have());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) == use_ima());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) == mac_apparmor_use());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "smack", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) == mac_smack_use());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "audit", false, false);
+ assert_se(condition);
assert_se(condition_test(condition) == use_audit());
condition_free(condition);
}
-
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 01ece022c1..03b3a9fa5c 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,14 +17,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdarg.h>
+#include <stdio.h>
+#include "alloc-util.h"
#include "conf-files.h"
+#include "fs-util.h"
#include "macro.h"
+#include "parse-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
-#include "rm-rf.h"
static void setup_test_dir(char *tmp_dir, const char *files, ...) {
va_list ap;
@@ -36,7 +39,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
va_start(ap, files);
while (files != NULL) {
_cleanup_free_ char *path = strappend(tmp_dir, files);
- assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0) == 0);
+ assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0);
files = va_arg(ap, const char *);
}
va_end(ap);
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index 463906d304..be5d2611f8 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -18,10 +18,11 @@
***/
#include "conf-parser.h"
+#include "log.h"
#include "macro.h"
-#include "util.h"
+#include "string-util.h"
#include "strv.h"
-#include "log.h"
+#include "util.h"
static void test_config_parse_path_one(const char *rvalue, const char *expected) {
char *path = NULL;
@@ -214,6 +215,14 @@ static void test_config_parse_nsec(void) {
test_config_parse_nsec_one("garbage", 0);
}
+static void test_config_parse_iec_uint64(void) {
+ uint64_t offset = 0;
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
+ assert_se(offset == 4 * 1024 * 1024);
+
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
@@ -229,6 +238,7 @@ int main(int argc, char **argv) {
test_config_parse_mode();
test_config_parse_sec();
test_config_parse_nsec();
+ test_config_parse_iec_uint64();
return 0;
}
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index b73c958ec5..ed1ea51dbd 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -19,14 +19,19 @@
#include <unistd.h>
+#include "alloc-util.h"
#include "copy.h"
-#include "path-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "log.h"
+#include "macro.h"
#include "mkdir.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
#include "strv.h"
-#include "macro.h"
#include "util.h"
-#include "rm-rf.h"
static void test_copy_file(void) {
_cleanup_free_ char *buf = NULL;
@@ -35,11 +40,13 @@ static void test_copy_file(void) {
size_t sz = 0;
int fd;
- fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
+ log_info("%s", __func__);
+
+ fd = mkostemp_safe(fn);
assert_se(fd >= 0);
close(fd);
- fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(fn_copy);
assert_se(fd >= 0);
close(fd);
@@ -62,9 +69,11 @@ static void test_copy_file_fd(void) {
char text[] = "boohoo\nfoo\n\tbar\n";
char buf[64] = {0};
- in_fd = mkostemp_safe(in_fn, O_RDWR);
+ log_info("%s", __func__);
+
+ in_fd = mkostemp_safe(in_fn);
assert_se(in_fd >= 0);
- out_fd = mkostemp_safe(out_fn, O_RDWR);
+ out_fd = mkostemp_safe(out_fn);
assert_se(out_fd >= 0);
assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0);
@@ -86,31 +95,43 @@ static void test_copy_tree(void) {
char **links = STRV_MAKE("link", "file",
"link2", "dir1/file");
char **p, **link;
+ const char *unixsockp;
+ struct stat st;
+
+ log_info("%s", __func__);
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
STRV_FOREACH(p, files) {
- char *f = strjoina(original_dir, *p);
+ _cleanup_free_ char *f;
+
+ assert_se(f = strappend(original_dir, *p));
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
}
STRV_FOREACH_PAIR(link, p, links) {
- char *f = strjoina(original_dir, *p);
- char *l = strjoina(original_dir, *link);
+ _cleanup_free_ char *f, *l;
+
+ assert_se(f = strappend(original_dir, *p));
+ assert_se(l = strappend(original_dir, *link));
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
}
+ unixsockp = strjoina(original_dir, "unixsock");
+ assert_se(mknod(unixsockp, S_IFSOCK|0644, 0) >= 0);
+
assert_se(copy_tree(original_dir, copy_dir, true) == 0);
STRV_FOREACH(p, files) {
- _cleanup_free_ char *buf = NULL;
+ _cleanup_free_ char *buf = NULL, *f;
size_t sz = 0;
- char *f = strjoina(copy_dir, *p);
+
+ assert_se(f = strappend(copy_dir, *p));
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
@@ -118,14 +139,19 @@ static void test_copy_tree(void) {
}
STRV_FOREACH_PAIR(link, p, links) {
- _cleanup_free_ char *target = NULL;
- char *f = strjoina(original_dir, *p);
- char *l = strjoina(copy_dir, *link);
+ _cleanup_free_ char *target = NULL, *f, *l;
+
+ assert_se(f = strjoin(original_dir, *p, NULL));
+ assert_se(l = strjoin(copy_dir, *link, NULL));
assert_se(readlink_and_canonicalize(l, &target) == 0);
assert_se(path_equal(f, target));
}
+ unixsockp = strjoina(copy_dir, "unixsock");
+ 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);
@@ -146,7 +172,7 @@ static void test_copy_bytes(void) {
assert_se(pipe2(pipefd, O_CLOEXEC) == 0);
- r = copy_bytes(infd, pipefd[1], (off_t) -1, false);
+ r = copy_bytes(infd, pipefd[1], (uint64_t) -1, false);
assert_se(r == 0);
r = read(pipefd[0], buf, sizeof(buf));
@@ -169,11 +195,65 @@ static void test_copy_bytes(void) {
assert_se(r == -EBADF);
}
+static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint64_t max_bytes) {
+ char fn2[] = "/tmp/test-copy-file-XXXXXX";
+ char fn3[] = "/tmp/test-copy-file-XXXXXX";
+ _cleanup_close_ int fd = -1, fd2 = -1, fd3 = -1;
+ int r;
+ struct stat buf, buf2, buf3;
+
+ log_info("%s try_reflink=%s max_bytes=%" PRIu64, __func__, yes_no(try_reflink), max_bytes);
+
+ fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ assert_se(fd >= 0);
+
+ fd2 = mkostemp_safe(fn2);
+ assert_se(fd2 >= 0);
+
+ fd3 = mkostemp_safe(fn3);
+ assert_se(fd3 >= 0);
+
+ r = copy_bytes(fd, fd2, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ assert_se(IN_SET(r, 0, 1));
+
+ assert_se(lseek(fd2, 0, SEEK_SET) == 0);
+
+ r = copy_bytes(fd2, fd3, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ /* We cannot distinguish between the input being exactly max_bytes
+ * or longer than max_bytes (without trying to read one more byte,
+ * or calling stat, or FION_READ, etc, and we don't want to do any
+ * of that). So we expect "truncation" since we know that file we
+ * are copying is exactly max_bytes bytes. */
+ assert_se(r == 1);
+
+ assert_se(fstat(fd, &buf) == 0);
+ assert_se(fstat(fd2, &buf2) == 0);
+ assert_se(fstat(fd3, &buf3) == 0);
+
+ assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes));
+ assert_se(buf3.st_size == buf2.st_size);
+
+ unlink(fn2);
+ unlink(fn3);
+}
+
int main(int argc, char *argv[]) {
test_copy_file();
test_copy_file_fd();
test_copy_tree();
test_copy_bytes();
+ test_copy_bytes_regular_file(argv[0], false, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], true, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], false, 1000); /* smaller than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 1000);
+ test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 32000);
return 0;
}
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
new file mode 100644
index 0000000000..8818d1ffb7
--- /dev/null
+++ b/src/test/test-cpu-set-util.c
@@ -0,0 +1,143 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "alloc-util.h"
+#include "cpu-set-util.h"
+#include "macro.h"
+
+static void test_parse_cpu_set(void) {
+ cpu_set_t *c = NULL;
+ int ncpus;
+ int cpu;
+
+ /* Simple range (from CPUAffinity example) */
+ ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
+ c = mfree(c);
+
+ /* A more interesting range */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Quoted strings */
+ ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Use commas as separators */
+ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Commas with spaces (and trailing comma, space) */
+ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 8; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges */
+ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges with trailing comma, space */
+ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Negative range (returns empty cpu_set) */
+ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
+ c = mfree(c);
+
+ /* Overlapping ranges */
+ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ for (cpu = 0; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Mix ranges and individual CPUs */
+ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
+ assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 4; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Garbage */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Range with garbage */
+ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Empty string */
+ c = NULL;
+ ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus == 0); /* empty string returns 0 */
+ assert_se(!c);
+
+ /* Runnaway quoted string */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+}
+
+int main(int argc, char *argv[]) {
+ test_parse_cpu_set();
+
+ return 0;
+}
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index 7e0ac754d1..a7cb426282 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,33 +19,46 @@
#include <unistd.h>
-#include "systemd/sd-daemon.h"
+#include "sd-daemon.h"
+
+#include "strv.h"
int main(int argc, char*argv[]) {
+ _cleanup_strv_free_ char **l = NULL;
+ int n, i;
+
+ n = sd_listen_fds_with_names(false, &l);
+ if (n < 0) {
+ log_error_errno(n, "Failed to get listening fds: %m");
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < n; i++)
+ log_info("fd=%i name=%s\n", SD_LISTEN_FDS_START + i, l[i]);
sd_notify(0,
"STATUS=Starting up");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Reloading\n"
"RELOADING=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Quitting\n"
"STOPPING=1");
- sleep(5);
+ sleep(1);
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-date.c b/src/test/test-date.c
index 00b569080c..7f497bb7d5 100644
--- a/src/test/test-date.c
+++ b/src/test/test-date.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,18 +19,22 @@
#include <string.h>
+#include "alloc-util.h"
+#include "string-util.h"
#include "util.h"
-static void test_one(const char *p) {
+static void test_should_pass(const char *p) {
usec_t t, q;
- char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp;
assert_se(parse_timestamp(p, &t) >= 0);
- format_timestamp(buf, sizeof(buf), t);
+ format_timestamp_us(buf, sizeof(buf), t);
log_info("%s", buf);
/* Chop off timezone */
- *strrchr(buf, ' ') = 0;
+ sp = strrchr(buf, ' ');
+ assert_se(sp);
+ *sp = 0;
assert_se(parse_timestamp(buf, &q) >= 0);
assert_se(q == t);
@@ -42,23 +44,57 @@ static void test_one(const char *p) {
assert_se(parse_timestamp(buf, &q) >= 0);
}
+static void test_should_parse(const char *p) {
+ usec_t t;
+
+ assert_se(parse_timestamp(p, &t) >= 0);
+}
+
+static void test_should_fail(const char *p) {
+ usec_t t;
+
+ assert_se(parse_timestamp(p, &t) < 0);
+}
+
+static void test_one(const char *p) {
+ _cleanup_free_ char *with_utc;
+
+ log_info("Test: %s", p);
+ with_utc = strjoin(p, " UTC", NULL);
+ test_should_pass(p);
+ test_should_pass(with_utc);
+}
+
+static void test_one_noutc(const char *p) {
+ _cleanup_free_ char *with_utc;
+
+ log_info("Test: %s", p);
+ with_utc = strjoin(p, " UTC", NULL);
+ test_should_pass(p);
+ test_should_fail(with_utc);
+}
+
int main(int argc, char *argv[]) {
test_one("17:41");
test_one("18:42:44");
+ test_one("18:42:44.0");
+ test_one("18:42:44.999999999999");
test_one("12-10-02 12:13:14");
test_one("12-10-2 12:13:14");
test_one("12-10-03 12:13");
test_one("2012-12-30 18:42");
test_one("2012-10-02");
test_one("Tue 2012-10-02");
- test_one("now");
+ test_one_noutc("now");
test_one("yesterday");
test_one("today");
test_one("tomorrow");
- test_one("+2d");
- test_one("+2y 4d");
- test_one("5months ago");
- test_one("@1395716396");
+ test_one_noutc("+2d");
+ test_one_noutc("+2y 4d");
+ test_one_noutc("5months ago");
+ test_one_noutc("@1395716396");
+ test_should_parse("today UTC");
+ test_should_fail("today UTC UTC");
return 0;
}
diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c
index 59ba4be087..af75b38948 100644
--- a/src/test/test-device-nodes.c
+++ b/src/test/test-device-nodes.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,7 +19,9 @@
#include <sys/types.h>
+#include "alloc-util.h"
#include "device-nodes.h"
+#include "string-util.h"
#include "util.h"
/* helpers for test_encode_devnode_name */
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 527cdd3b54..e2f097c95e 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "macro.h"
+#include "alloc-util.h"
#include "dns-domain.h"
+#include "macro.h"
+#include "string-util.h"
static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
char buffer[buffer_sz];
@@ -37,7 +37,7 @@ static void test_dns_label_unescape_one(const char *what, const char *expect, si
static void test_dns_label_unescape(void) {
test_dns_label_unescape_one("hallo", "hallo", 6, 5);
- test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC);
+ test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS);
test_dns_label_unescape_one("", "", 10, 0);
test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12);
test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5);
@@ -48,13 +48,114 @@ static void test_dns_label_unescape(void) {
test_dns_label_unescape_one("..", "", 20, -EINVAL);
test_dns_label_unescape_one(".foobar", "", 20, -EINVAL);
test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
+ test_dns_label_unescape_one("foobar..", "foobar", 20, -EINVAL);
+}
+
+static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
+ uint8_t buffer[buffer_sz];
+ int r;
+
+ r = dns_name_to_wire_format(what, buffer, buffer_sz, false);
+ assert_se(r == ret);
+
+ if (r < 0)
+ return;
+
+ assert_se(!memcmp(buffer, expect, r));
+}
+
+static void test_dns_name_to_wire_format(void) {
+ static const char out0[] = { 0 };
+ static const char out1[] = { 3, 'f', 'o', 'o', 0 };
+ static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+ static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+ static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+ 3, 'a', '1', '2', 0 };
+
+ test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0));
+
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
+
+ test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
+ test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
+
+ test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
+
+ test_dns_name_to_wire_format_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", NULL, 500, -EINVAL);
+ test_dns_name_to_wire_format_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", out4, sizeof(out4), sizeof(out4));
+}
+
+static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
+ char buffer[buffer_sz];
+ const char *label;
+ int r;
+
+ label = what + strlen(what);
+
+ r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
+ assert_se(r == ret1);
+ if (r >= 0)
+ assert_se(streq(buffer, expect1));
+
+ r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
+ assert_se(r == ret2);
+ if (r >= 0)
+ assert_se(streq(buffer, expect2));
+}
+
+static void test_dns_label_unescape_suffix(void) {
+ test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0);
+ test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOBUFS, -ENOBUFS);
+ test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0);
+ test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0);
+ test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5);
+ test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0);
+ test_dns_label_unescape_suffix_one("..", "", "", 20, 0, -EINVAL);
+ test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL);
+ test_dns_label_unescape_suffix_one("foobar.", "foobar", "", 20, 6, 0);
+ test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3);
+ test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL);
+ test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL);
+ test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4);
+ test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0);
}
static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) {
_cleanup_free_ char *t = NULL;
int r;
- r = dns_label_escape(what, l, &t);
+ r = dns_label_escape_new(what, l, &t);
assert_se(r == ret);
if (r < 0)
@@ -64,9 +165,9 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
}
static void test_dns_label_escape(void) {
- test_dns_label_escape_one("", 0, "", 0);
+ test_dns_label_escape_one("", 0, NULL, -EINVAL);
test_dns_label_escape_one("hallo", 5, "hallo", 5);
- test_dns_label_escape_one("hallo", 6, NULL, -EINVAL);
+ test_dns_label_escape_one("hallo", 6, "hallo\\000", 9);
test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31);
}
@@ -84,15 +185,15 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
}
static void test_dns_name_normalize(void) {
- test_dns_name_normalize_one("", "", 0);
+ test_dns_name_normalize_one("", ".", 0);
test_dns_name_normalize_one("f", "f", 0);
test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
- test_dns_name_normalize_one("\\000", NULL, -EINVAL);
+ test_dns_name_normalize_one("\\000", "\\000", 0);
test_dns_name_normalize_one("..", NULL, -EINVAL);
test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
test_dns_name_normalize_one("foobar.", "foobar", 0);
- test_dns_name_normalize_one(".", "", 0);
+ test_dns_name_normalize_one(".", ".", 0);
}
static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
@@ -114,12 +215,44 @@ static void test_dns_name_equal(void) {
test_dns_name_equal_one("abc.def", "CBA.def", false);
test_dns_name_equal_one("", "xxx", false);
test_dns_name_equal_one("ab", "a", false);
- test_dns_name_equal_one("\\000", "xxxx", -EINVAL);
+ test_dns_name_equal_one("\\000", "\\000", true);
test_dns_name_equal_one(".", "", true);
test_dns_name_equal_one(".", ".", true);
test_dns_name_equal_one("..", "..", -EINVAL);
}
+static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) {
+ int r;
+
+ r = dns_name_between(a, b, c);
+ assert_se(r == ret);
+
+ r = dns_name_between(c, b, a);
+ if (ret >= 0)
+ assert_se(r == 0);
+ else
+ assert_se(r == ret);
+}
+
+static void test_dns_name_between(void) {
+ /* see https://tools.ietf.org/html/rfc4034#section-6.1
+ Note that we use "\033.z.example" in stead of "\001.z.example" as we
+ consider the latter invalid */
+ test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true);
+ test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true);
+ test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true);
+ test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true);
+ test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true);
+ test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true);
+ test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true);
+ test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true);
+ test_dns_name_between_one("\\200.z.example", "example", "a.example", true);
+
+ test_dns_name_between_one("example", "a.example", "example", -EINVAL);
+ test_dns_name_between_one("example", "example", "yljkjljk.a.example", false);
+ test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false);
+}
+
static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
assert_se(dns_name_endswith(a, b) == ret);
}
@@ -142,21 +275,40 @@ static void test_dns_name_endswith(void) {
test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
}
-static void test_dns_name_root(void) {
- assert_se(dns_name_root("") == true);
- assert_se(dns_name_root(".") == true);
- assert_se(dns_name_root("xxx") == false);
- assert_se(dns_name_root("xxx.") == false);
- assert_se(dns_name_root("..") == -EINVAL);
+static void test_dns_name_startswith_one(const char *a, const char *b, int ret) {
+ assert_se(dns_name_startswith(a, b) == ret);
}
-static void test_dns_name_single_label(void) {
- assert_se(dns_name_single_label("") == false);
- assert_se(dns_name_single_label(".") == false);
- assert_se(dns_name_single_label("..") == -EINVAL);
- assert_se(dns_name_single_label("x") == true);
- assert_se(dns_name_single_label("x.") == true);
- assert_se(dns_name_single_label("xx.yy") == false);
+static void test_dns_name_startswith(void) {
+ test_dns_name_startswith_one("", "", true);
+ test_dns_name_startswith_one("", "xxx", false);
+ test_dns_name_startswith_one("xxx", "", true);
+ test_dns_name_startswith_one("x", "x", true);
+ test_dns_name_startswith_one("x", "y", false);
+ test_dns_name_startswith_one("x.y", "x.y", true);
+ test_dns_name_startswith_one("x.y", "y.x", false);
+ test_dns_name_startswith_one("x.y", "x", true);
+ test_dns_name_startswith_one("x.y", "X", true);
+ test_dns_name_startswith_one("x.y", "y", false);
+ test_dns_name_startswith_one("x.y", "", true);
+ test_dns_name_startswith_one("x.y", "X", true);
+}
+
+static void test_dns_name_is_root(void) {
+ assert_se(dns_name_is_root(""));
+ assert_se(dns_name_is_root("."));
+ assert_se(!dns_name_is_root("xxx"));
+ assert_se(!dns_name_is_root("xxx."));
+ assert_se(!dns_name_is_root(".."));
+}
+
+static void test_dns_name_is_single_label(void) {
+ assert_se(!dns_name_is_single_label(""));
+ assert_se(!dns_name_is_single_label("."));
+ assert_se(!dns_name_is_single_label(".."));
+ assert_se(dns_name_is_single_label("x"));
+ assert_se(dns_name_is_single_label("x."));
+ assert_se(!dns_name_is_single_label("xx.yy"));
}
static void test_dns_name_reverse_one(const char *address, const char *name) {
@@ -175,18 +327,333 @@ static void test_dns_name_reverse_one(const char *address, const char *name) {
static void test_dns_name_reverse(void) {
test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa");
test_dns_name_reverse_one("fe80::47", "7.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa");
+ test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa");
+ test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
+}
+
+static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) {
+ _cleanup_free_ char *p = NULL;
+
+ assert_se(dns_name_concat(a, b, &p) == r);
+ assert_se(streq_ptr(p, result));
+}
+
+static void test_dns_name_concat(void) {
+ test_dns_name_concat_one("", "", 0, ".");
+ test_dns_name_concat_one(".", "", 0, ".");
+ test_dns_name_concat_one("", ".", 0, ".");
+ test_dns_name_concat_one(".", ".", 0, ".");
+ test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
+ test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
+ test_dns_name_concat_one("foo", NULL, 0, "foo");
+ test_dns_name_concat_one("foo", ".", 0, "foo");
+ test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
+ test_dns_name_concat_one(NULL, NULL, 0, ".");
+ test_dns_name_concat_one(NULL, ".", 0, ".");
+ test_dns_name_concat_one(NULL, "foo", 0, "foo");
+}
+
+static void test_dns_name_is_valid_one(const char *s, int ret) {
+ assert_se(dns_name_is_valid(s) == ret);
+}
+
+static void test_dns_name_is_valid(void) {
+ test_dns_name_is_valid_one("foo", 1);
+ test_dns_name_is_valid_one("foo.", 1);
+ test_dns_name_is_valid_one("foo..", 0);
+ test_dns_name_is_valid_one("Foo", 1);
+ test_dns_name_is_valid_one("foo.bar", 1);
+ test_dns_name_is_valid_one("foo.bar.baz", 1);
+ test_dns_name_is_valid_one("", 1);
+ test_dns_name_is_valid_one("foo..bar", 0);
+ test_dns_name_is_valid_one(".foo.bar", 0);
+ test_dns_name_is_valid_one("foo.bar.", 1);
+ test_dns_name_is_valid_one("foo.bar..", 0);
+ test_dns_name_is_valid_one("\\zbar", 0);
+ test_dns_name_is_valid_one("ä", 1);
+ test_dns_name_is_valid_one("\n", 0);
+
+ /* 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*/
+ 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*/
+ 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*/
+ 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 */
+ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0);
+
+ /* label of 63 chars length */
+ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1);
+}
+
+static void test_dns_service_name_is_valid(void) {
+ assert_se(dns_service_name_is_valid("Lennart's Compüter"));
+ assert_se(dns_service_name_is_valid("piff.paff"));
+
+ assert_se(!dns_service_name_is_valid(NULL));
+ assert_se(!dns_service_name_is_valid(""));
+ assert_se(!dns_service_name_is_valid("foo\nbar"));
+ assert_se(!dns_service_name_is_valid("foo\201bar"));
+ assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters"));
+}
+
+static void test_dns_srv_type_is_valid(void) {
+
+ assert_se(dns_srv_type_is_valid("_http._tcp"));
+ assert_se(dns_srv_type_is_valid("_foo-bar._tcp"));
+ assert_se(dns_srv_type_is_valid("_w._udp"));
+ assert_se(dns_srv_type_is_valid("_a800._tcp"));
+ assert_se(dns_srv_type_is_valid("_a-800._tcp"));
+
+ assert_se(!dns_srv_type_is_valid(NULL));
+ assert_se(!dns_srv_type_is_valid(""));
+ assert_se(!dns_srv_type_is_valid("x"));
+ assert_se(!dns_srv_type_is_valid("_foo"));
+ assert_se(!dns_srv_type_is_valid("_tcp"));
+ assert_se(!dns_srv_type_is_valid("_"));
+ assert_se(!dns_srv_type_is_valid("_foo."));
+ assert_se(!dns_srv_type_is_valid("_föo._tcp"));
+ assert_se(!dns_srv_type_is_valid("_f\no._tcp"));
+ assert_se(!dns_srv_type_is_valid("_800._tcp"));
+ assert_se(!dns_srv_type_is_valid("_-800._tcp"));
+ assert_se(!dns_srv_type_is_valid("_-foo._tcp"));
+ assert_se(!dns_srv_type_is_valid("_piep._foo._udp"));
+}
+
+static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) {
+ _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
+
+ assert_se(dns_service_join(a, b, c, &t) == r);
+ assert_se(streq_ptr(t, d));
+
+ if (r < 0)
+ return;
+
+ assert_se(dns_service_split(t, &x, &y, &z) >= 0);
+ assert_se(streq_ptr(a, x));
+ assert_se(streq_ptr(b, y));
+ assert_se(dns_name_equal(c, z) > 0);
+}
+
+static void test_dns_service_join(void) {
+ test_dns_service_join_one("", "", "", -EINVAL, NULL);
+ test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL);
+ test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL);
+ test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL);
+ test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL);
+
+ test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp");
+ test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp");
+ test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo");
+ test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo");
+ test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com");
+ test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com");
+}
+
+static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) {
+ _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
+
+ assert_se(dns_service_split(joined, &x, &y, &z) == r);
+ assert_se(streq_ptr(x, a));
+ assert_se(streq_ptr(y, b));
+ assert_se(streq_ptr(z, c));
+
+ if (r < 0)
+ return;
+
+ if (y) {
+ assert_se(dns_service_join(x, y, z, &t) == 0);
+ assert_se(dns_name_equal(joined, t) > 0);
+ } else
+ assert_se(!x && dns_name_equal(z, joined) > 0);
+}
+
+static void test_dns_service_split(void) {
+ test_dns_service_split_one("", NULL, NULL, ".", 0);
+ test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
+ test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
+ test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
+ test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
+ test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
+ test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
+}
+
+static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) {
+ _cleanup_free_ char *s = NULL;
+
+ assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r);
+ assert_se(streq_ptr(s, result));
+}
+
+static void test_dns_name_change_suffix(void) {
+ test_dns_name_change_suffix_one("foo.bar", "bar", "waldo", 1, "foo.waldo");
+ test_dns_name_change_suffix_one("foo.bar.waldi.quux", "foo.bar.waldi.quux", "piff.paff", 1, "piff.paff");
+ test_dns_name_change_suffix_one("foo.bar.waldi.quux", "bar.waldi.quux", "piff.paff", 1, "foo.piff.paff");
+ test_dns_name_change_suffix_one("foo.bar.waldi.quux", "waldi.quux", "piff.paff", 1, "foo.bar.piff.paff");
+ test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
+ test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
+ test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
+ test_dns_name_change_suffix_one("", "", "", 1, ".");
+ test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
+}
+
+static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) {
+ const char *p = NULL;
+
+ assert_se(ret == dns_name_suffix(name, n_labels, &p));
+ assert_se(streq_ptr(p, result));
+}
+
+static void test_dns_name_suffix(void) {
+ test_dns_name_suffix_one("foo.bar", 2, "foo.bar", 0);
+ test_dns_name_suffix_one("foo.bar", 1, "bar", 1);
+ test_dns_name_suffix_one("foo.bar", 0, "", 2);
+ test_dns_name_suffix_one("foo.bar", 3, NULL, -EINVAL);
+ test_dns_name_suffix_one("foo.bar", 4, NULL, -EINVAL);
+
+ test_dns_name_suffix_one("bar", 1, "bar", 0);
+ test_dns_name_suffix_one("bar", 0, "", 1);
+ test_dns_name_suffix_one("bar", 2, NULL, -EINVAL);
+ test_dns_name_suffix_one("bar", 3, NULL, -EINVAL);
+
+ test_dns_name_suffix_one("", 0, "", 0);
+ test_dns_name_suffix_one("", 1, NULL, -EINVAL);
+ test_dns_name_suffix_one("", 2, NULL, -EINVAL);
+}
+
+static void test_dns_name_count_labels_one(const char *name, int n) {
+ assert_se(dns_name_count_labels(name) == n);
+}
+
+static void test_dns_name_count_labels(void) {
+ test_dns_name_count_labels_one("foo.bar.quux.", 3);
+ test_dns_name_count_labels_one("foo.bar.quux", 3);
+ test_dns_name_count_labels_one("foo.bar.", 2);
+ test_dns_name_count_labels_one("foo.bar", 2);
+ test_dns_name_count_labels_one("foo.", 1);
+ test_dns_name_count_labels_one("foo", 1);
+ test_dns_name_count_labels_one("", 0);
+ test_dns_name_count_labels_one(".", 0);
+ test_dns_name_count_labels_one("..", -EINVAL);
+}
+
+static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) {
+ assert_se(dns_name_equal_skip(a, n_labels, b) == ret);
+}
+
+static void test_dns_name_equal_skip(void) {
+ test_dns_name_equal_skip_one("foo", 0, "bar", 0);
+ test_dns_name_equal_skip_one("foo", 0, "foo", 1);
+ test_dns_name_equal_skip_one("foo", 1, "foo", 0);
+ test_dns_name_equal_skip_one("foo", 2, "foo", 0);
+
+ test_dns_name_equal_skip_one("foo.bar", 0, "foo.bar", 1);
+ test_dns_name_equal_skip_one("foo.bar", 1, "foo.bar", 0);
+ test_dns_name_equal_skip_one("foo.bar", 2, "foo.bar", 0);
+ test_dns_name_equal_skip_one("foo.bar", 3, "foo.bar", 0);
+
+ test_dns_name_equal_skip_one("foo.bar", 0, "bar", 0);
+ test_dns_name_equal_skip_one("foo.bar", 1, "bar", 1);
+ test_dns_name_equal_skip_one("foo.bar", 2, "bar", 0);
+ test_dns_name_equal_skip_one("foo.bar", 3, "bar", 0);
+
+ test_dns_name_equal_skip_one("foo.bar", 0, "", 0);
+ test_dns_name_equal_skip_one("foo.bar", 1, "", 0);
+ test_dns_name_equal_skip_one("foo.bar", 2, "", 1);
+ test_dns_name_equal_skip_one("foo.bar", 3, "", 0);
+
+ test_dns_name_equal_skip_one("", 0, "", 1);
+ test_dns_name_equal_skip_one("", 1, "", 0);
+ test_dns_name_equal_skip_one("", 1, "foo", 0);
+ test_dns_name_equal_skip_one("", 2, "foo", 0);
+}
+
+static void test_dns_name_compare_func(void) {
+ assert_se(dns_name_compare_func("", "") == 0);
+ assert_se(dns_name_compare_func("", ".") == 0);
+ assert_se(dns_name_compare_func(".", "") == 0);
+ assert_se(dns_name_compare_func("foo", "foo.") == 0);
+ assert_se(dns_name_compare_func("foo.", "foo") == 0);
+ assert_se(dns_name_compare_func("foo", "foo") == 0);
+ assert_se(dns_name_compare_func("foo.", "foo.") == 0);
+ assert_se(dns_name_compare_func("heise.de", "HEISE.DE.") == 0);
+
+ assert_se(dns_name_compare_func("de.", "heise.de") != 0);
+}
+
+static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) {
+ const char *c;
+
+ assert_se(dns_name_common_suffix(a, b, &c) >= 0);
+ assert_se(streq(c, result));
+}
+
+static void test_dns_name_common_suffix(void) {
+ test_dns_name_common_suffix_one("", "", "");
+ test_dns_name_common_suffix_one("foo", "", "");
+ test_dns_name_common_suffix_one("", "foo", "");
+ test_dns_name_common_suffix_one("foo", "bar", "");
+ test_dns_name_common_suffix_one("bar", "foo", "");
+ test_dns_name_common_suffix_one("foo", "foo", "foo");
+ test_dns_name_common_suffix_one("quux.foo", "foo", "foo");
+ test_dns_name_common_suffix_one("foo", "quux.foo", "foo");
+ test_dns_name_common_suffix_one("this.is.a.short.sentence", "this.is.another.short.sentence", "short.sentence");
+ test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR");
+}
+
+static void test_dns_name_apply_idna_one(const char *s, const char *result) {
+#ifdef HAVE_LIBIDN
+ _cleanup_free_ char *buf = NULL;
+ assert_se(dns_name_apply_idna(s, &buf) >= 0);
+ assert_se(dns_name_equal(buf, result) > 0);
+#endif
+}
+
+static void test_dns_name_apply_idna(void) {
+ test_dns_name_apply_idna_one("", "");
+ test_dns_name_apply_idna_one("foo", "foo");
+ test_dns_name_apply_idna_one("foo.", "foo");
+ test_dns_name_apply_idna_one("foo.bar", "foo.bar");
+ test_dns_name_apply_idna_one("foo.bar.", "foo.bar");
+ test_dns_name_apply_idna_one("föö", "xn--f-1gaa");
+ test_dns_name_apply_idna_one("föö.", "xn--f-1gaa");
+ test_dns_name_apply_idna_one("föö.bär", "xn--f-1gaa.xn--br-via");
+ test_dns_name_apply_idna_one("föö.bär.", "xn--f-1gaa.xn--br-via");
}
int main(int argc, char *argv[]) {
test_dns_label_unescape();
+ test_dns_label_unescape_suffix();
test_dns_label_escape();
test_dns_name_normalize();
test_dns_name_equal();
test_dns_name_endswith();
- test_dns_name_root();
- test_dns_name_single_label();
+ test_dns_name_startswith();
+ test_dns_name_between();
+ test_dns_name_is_root();
+ test_dns_name_is_single_label();
test_dns_name_reverse();
+ test_dns_name_concat();
+ test_dns_name_is_valid();
+ test_dns_name_to_wire_format();
+ test_dns_service_name_is_valid();
+ test_dns_srv_type_is_valid();
+ test_dns_service_join();
+ test_dns_service_split();
+ test_dns_name_change_suffix();
+ test_dns_name_suffix();
+ test_dns_name_count_labels();
+ test_dns_name_equal_skip();
+ test_dns_name_compare_func();
+ test_dns_name_common_suffix();
+ test_dns_name_apply_idna();
return 0;
}
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index 27df9089c3..d4f09b08a5 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,9 +19,11 @@
#include <stdio.h>
-#include "util.h"
-#include "terminal-util.h"
+#include "alloc-util.h"
#include "def.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "util.h"
static void test_one(const char *p) {
_cleanup_free_ char *t;
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index a7ab21a415..a651f6b683 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,15 +17,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <errno.h>
+#include <stdio.h>
#include <string.h>
-#include "manager.h"
#include "bus-util.h"
+#include "manager.h"
+#include "rm-rf.h"
+#include "test-helper.h"
+#include "tests.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
Manager *m = NULL;
Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
FILE *serial = NULL;
@@ -35,11 +37,13 @@ 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);
- r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ r = manager_new(UNIT_FILE_USER, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ log_notice_errno(r, "Skipping test: manager_new: %m");
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
@@ -52,7 +56,7 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test1: (Trivial)\n");
- r = manager_add_job(m, JOB_START, c, JOB_REPLACE, false, &err, &j);
+ r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j);
if (sd_bus_error_is_set(&err))
log_error("error: %s: %s", err.name, err.message);
assert_se(r == 0);
@@ -65,15 +69,15 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test2: (Cyclic Order, Unfixable)\n");
- assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK);
manager_dump_jobs(m, stdout, "\t");
printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test4: (Identical transaction)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Load3:\n");
@@ -81,21 +85,21 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test5: (Colliding transaction, fail)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test6: (Colliding transaction, replace)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test7: (Unmergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, false, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test8: (Mergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Test9: (Unmergeable job type, replace)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
printf("Load4:\n");
@@ -103,7 +107,7 @@ int main(int argc, char *argv[]) {
manager_dump_units(m, stdout, "\t");
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
- assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, false, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
manager_free(m);
diff --git a/src/test/test-env-replace.c b/src/test/test-env-util.c
index 2e28c0c49b..35bb62906e 100644
--- a/src/test/test-env-replace.c
+++ b/src/test/test-env-util.c
@@ -1,9 +1,8 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
+ 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
@@ -21,9 +20,10 @@
#include <string.h>
-#include "util.h"
-#include "strv.h"
#include "env-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
static void test_strv_env_delete(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
@@ -118,6 +118,8 @@ static void test_replace_env_arg(void) {
"$FOO$FOO",
"${FOO}${BAR}",
"${FOO",
+ "FOO$$${FOO}",
+ "$$FOO${FOO}",
NULL
};
_cleanup_strv_free_ char **r = NULL;
@@ -133,7 +135,9 @@ static void test_replace_env_arg(void) {
assert_se(streq(r[6], "BAR"));
assert_se(streq(r[7], "BAR BARwaldo"));
assert_se(streq(r[8], "${FOO"));
- assert_se(strv_length(r) == 9);
+ assert_se(streq(r[9], "FOO$BAR BAR"));
+ assert_se(streq(r[10], "$FOOBAR BAR"));
+ assert_se(strv_length(r) == 11);
}
static void test_env_clean(void) {
@@ -174,10 +178,37 @@ static void test_env_name_is_valid(void) {
assert_se(!env_name_is_valid(NULL));
assert_se(!env_name_is_valid(""));
+ assert_se(!env_name_is_valid("xxx\a"));
+ assert_se(!env_name_is_valid("xxx\007b"));
+ assert_se(!env_name_is_valid("\007\009"));
assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
}
+static void test_env_value_is_valid(void) {
+ assert_se(env_value_is_valid(""));
+ assert_se(env_value_is_valid("głąb kapuściany"));
+ assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+}
+
+static void test_env_assignment_is_valid(void) {
+ assert_se(env_assignment_is_valid("a="));
+ assert_se(env_assignment_is_valid("b=głąb kapuściany"));
+ assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
+ assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+
+ assert_se(!env_assignment_is_valid("="));
+ assert_se(!env_assignment_is_valid("a b="));
+ assert_se(!env_assignment_is_valid("a ="));
+ assert_se(!env_assignment_is_valid(" b="));
+ /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
+ assert_se(!env_assignment_is_valid("a.b="));
+ assert_se(!env_assignment_is_valid("a-b="));
+ assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
+ assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
+ assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
+}
+
int main(int argc, char *argv[]) {
test_strv_env_delete();
test_strv_env_unset();
@@ -186,6 +217,8 @@ int main(int argc, char *argv[]) {
test_replace_env_arg();
test_env_clean();
test_env_name_is_valid();
+ test_env_value_is_valid();
+ test_env_assignment_is_valid();
return 0;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
new file mode 100644
index 0000000000..6cbb8443fe
--- /dev/null
+++ b/src/test/test-escape.c
@@ -0,0 +1,114 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "alloc-util.h"
+#include "escape.h"
+#include "macro.h"
+
+static void test_cescape(void) {
+ _cleanup_free_ char *escaped;
+
+ assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+ assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_cunescape(void) {
+ _cleanup_free_ char *unescaped;
+
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+ unescaped = mfree(unescaped);
+
+ /* incomplete sequences */
+ assert_se(cunescape("\\x0", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x0"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\x", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\", 0, &unescaped) < 0);
+ assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\11", 0, &unescaped) < 0);
+ assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\11"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\1", 0, &unescaped) < 0);
+ assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\1"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
+ assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "ßßΠA"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\073", 0, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, ";"));
+}
+
+static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_escape(s, bad));
+ assert_se(streq_ptr(r, expected));
+}
+
+static void test_shell_escape(void) {
+ test_shell_escape_one("", "", "");
+ test_shell_escape_one("\\", "", "\\\\");
+ test_shell_escape_one("foobar", "", "foobar");
+ test_shell_escape_one("foobar", "o", "f\\o\\obar");
+ test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
+}
+
+static void test_shell_maybe_quote_one(const char *s, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_maybe_quote(s));
+ assert_se(streq(r, expected));
+}
+
+static void test_shell_maybe_quote(void) {
+
+ test_shell_maybe_quote_one("", "");
+ test_shell_maybe_quote_one("\\", "\"\\\\\"");
+ test_shell_maybe_quote_one("\"", "\"\\\"\"");
+ test_shell_maybe_quote_one("foobar", "foobar");
+ test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
+ test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
+}
+
+int main(int argc, char *argv[]) {
+ test_cescape();
+ test_cunescape();
+ test_shell_escape();
+ test_shell_maybe_quote();
+
+ return 0;
+}
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 0f4172e722..8b4ff22495 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -17,14 +17,26 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <grp.h>
+#include <pwd.h>
#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
-#include "unit.h"
-#include "manager.h"
-#include "util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
+#include "manager.h"
#include "mkdir.h"
+#include "path-util.h"
#include "rm-rf.h"
+#ifdef HAVE_SECCOMP
+#include "seccomp-util.h"
+#endif
+#include "test-helper.h"
+#include "unit.h"
+#include "util.h"
+#include "virt.h"
typedef void (*test_function_t)(Manager *m);
@@ -77,10 +89,24 @@ static void test_exec_workingdirectory(Manager *m) {
}
static void test_exec_personality(Manager *m) {
- test(m, "exec-personality-x86.service", 0, CLD_EXITED);
-
#if defined(__x86_64__)
test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
+
+#elif defined(__s390__)
+ test(m, "exec-personality-s390.service", 0, CLD_EXITED);
+
+#elif defined(__powerpc64__)
+# if __BYTE_ORDER == __BIG_ENDIAN
+ test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
+# else
+ test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
+# endif
+
+#elif defined(__aarch64__)
+ test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
+
+#elif defined(__i386__)
+ test(m, "exec-personality-x86.service", 0, CLD_EXITED);
#endif
}
@@ -99,31 +125,84 @@ 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");
+ return;
+ }
test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
}
+static void test_exec_privatedevices_capabilities(Manager *m) {
+ if (detect_container() > 0) {
+ log_notice("testing in container, skipping private device tests");
+ return;
+ }
+ test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
+ test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
+}
+
+static void test_exec_readonlypaths(Manager *m) {
+ test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
+ test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
+}
+
+static void test_exec_readwritepaths(Manager *m) {
+ test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
+}
+
+static void test_exec_inaccessiblepaths(Manager *m) {
+ test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
+}
+
static void test_exec_systemcallfilter(Manager *m) {
#ifdef HAVE_SECCOMP
+ if (!is_seccomp_available())
+ return;
test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
+
#endif
}
static void test_exec_systemcallerrornumber(Manager *m) {
#ifdef HAVE_SECCOMP
- test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED);
+ if (is_seccomp_available())
+ test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED);
+#endif
+}
+
+static void test_exec_systemcall_system_mode_with_user(Manager *m) {
+#ifdef HAVE_SECCOMP
+ if (!is_seccomp_available())
+ return;
+ if (getpwnam("nobody"))
+ test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
+ 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");
#endif
}
static void test_exec_user(Manager *m) {
- test(m, "exec-user.service", 0, CLD_EXITED);
+ if (getpwnam("nobody"))
+ test(m, "exec-user.service", 0, CLD_EXITED);
+ 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");
}
static void test_exec_group(Manager *m) {
- test(m, "exec-group.service", 0, CLD_EXITED);
+ if (getgrnam("nobody"))
+ test(m, "exec-group.service", 0, CLD_EXITED);
+ 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");
}
static void test_exec_environment(Manager *m) {
@@ -132,28 +211,187 @@ static void test_exec_environment(Manager *m) {
test(m, "exec-environment-empty.service", 0, CLD_EXITED);
}
+static void test_exec_environmentfile(Manager *m) {
+ static const char e[] =
+ "VAR1='word1 word2'\n"
+ "VAR2=word3 \n"
+ "# comment1\n"
+ "\n"
+ "; comment2\n"
+ " ; # comment3\n"
+ "line without an equal\n"
+ "VAR3='$word 5 6'\n";
+ int r;
+
+ r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
+ assert_se(r == 0);
+
+ test(m, "exec-environmentfile.service", 0, CLD_EXITED);
+
+ unlink("/tmp/test-exec_environmentfile.conf");
+}
+
+static void test_exec_passenvironment(Manager *m) {
+ /* test-execute runs under MANAGER_USER which, by default, forwards all
+ * variables present in the environment, but only those that are
+ * present _at the time it is created_!
+ *
+ * So these PassEnvironment checks are still expected to work, since we
+ * are ensuring the variables are not present at manager creation (they
+ * are unset explicitly in main) and are only set here.
+ *
+ * This is still a good approximation of how a test for MANAGER_SYSTEM
+ * would work.
+ */
+ assert_se(setenv("VAR1", "word1 word2", 1) == 0);
+ assert_se(setenv("VAR2", "word3", 1) == 0);
+ assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
+ test(m, "exec-passenvironment.service", 0, CLD_EXITED);
+ test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
+ test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
+ assert_se(unsetenv("VAR1") == 0);
+ assert_se(unsetenv("VAR2") == 0);
+ assert_se(unsetenv("VAR3") == 0);
+ test(m, "exec-passenvironment-absent.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);
}
+static void test_exec_runtimedirectory(Manager *m) {
+ test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
+ test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
+ if (getgrnam("nobody"))
+ test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ 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");
+}
+
+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");
+ return;
+ }
+
+ test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
+}
+
+static void test_exec_capabilityambientset(Manager *m) {
+ int r;
+
+ /* Check if the kernel has support for ambient capabilities. Run
+ * the tests only if that's the case. Clearing all ambient
+ * capabilities is fine, since we are expecting them to be unset
+ * in the first place for the tests. */
+ r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+ if (r >= 0 || errno != EINVAL) {
+ if (getpwnam("nobody")) {
+ test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
+ } else if (getpwnam("nfsnobody")) {
+ 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");
+ } else
+ log_error_errno(errno, "Skipping test_exec_capabilityambientset, the kernel does not support ambient capabilities: %m");
+}
+
+static void test_exec_privatenetwork(Manager *m) {
+ int r;
+
+ r = find_binary("ip", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping test_exec_privatenetwork, could not find ip binary: %m");
+ return;
+ }
+
+ test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
+}
+
+static void test_exec_oomscoreadjust(Manager *m) {
+ test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
+ test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
+}
+
+static void test_exec_ioschedulingclass(Manager *m) {
+ test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
+}
+
+static void test_exec_spec_interpolation(Manager *m) {
+ test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
+}
+
+static int run_tests(UnitFileScope scope, test_function_t *tests) {
+ test_function_t *test = NULL;
+ Manager *m = NULL;
+ int r;
+
+ assert_se(tests);
+
+ r = manager_new(scope, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ log_notice_errno(r, "Skipping test: manager_new: %m");
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ for (test = tests; test && *test; test++)
+ (*test)(m);
+
+ manager_free(m);
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
- test_function_t tests[] = {
+ test_function_t user_tests[] = {
test_exec_workingdirectory,
test_exec_personality,
test_exec_ignoresigpipe,
test_exec_privatetmp,
test_exec_privatedevices,
+ test_exec_privatedevices_capabilities,
+ test_exec_readonlypaths,
+ test_exec_readwritepaths,
+ test_exec_inaccessiblepaths,
+ test_exec_privatenetwork,
test_exec_systemcallfilter,
test_exec_systemcallerrornumber,
test_exec_user,
test_exec_group,
test_exec_environment,
+ test_exec_environmentfile,
+ test_exec_passenvironment,
test_exec_umask,
+ test_exec_runtimedirectory,
+ test_exec_capabilityboundingset,
+ test_exec_capabilityambientset,
+ test_exec_oomscoreadjust,
+ test_exec_ioschedulingclass,
+ test_exec_spec_interpolation,
+ NULL,
+ };
+ test_function_t system_tests[] = {
+ test_exec_systemcall_system_mode_with_user,
NULL,
};
- test_function_t *test = NULL;
- Manager *m = NULL;
int r;
log_parse_environment();
@@ -165,20 +403,22 @@ int main(int argc, char *argv[]) {
return EXIT_TEST_SKIP;
}
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
+ assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0);
- r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
- return EXIT_TEST_SKIP;
- }
- assert_se(r >= 0);
- assert_se(manager_startup(m, NULL, NULL) >= 0);
+ /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
+ * cases, otherwise (and if they are present in the environment),
+ * `manager_default_environment` will copy them into the default
+ * environment which is passed to each created job, which will make the
+ * tests that expect those not to be present to fail.
+ */
+ assert_se(unsetenv("VAR1") == 0);
+ assert_se(unsetenv("VAR2") == 0);
+ assert_se(unsetenv("VAR3") == 0);
- for (test = tests; test && *test; test++)
- (*test)(m);
+ r = run_tests(UNIT_FILE_USER, user_tests);
+ if (r != 0)
+ return r;
- manager_free(m);
-
- return 0;
+ return run_tests(UNIT_FILE_SYSTEM, system_tests);
}
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
new file mode 100644
index 0000000000..7a23fa7b7b
--- /dev/null
+++ b/src/test/test-extract-word.c
@@ -0,0 +1,556 @@
+/***
+ 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 <stdlib.h>
+#include <string.h>
+
+#include "extract-word.h"
+#include "log.h"
+#include "string-util.h"
+
+static void test_extract_first_word(void) {
+ const char *p, *original;
+ char *t;
+
+ p = original = "foobar waldo";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 7);
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "\"foobar\""));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "\'waldo\'"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\""));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\'"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\'";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\'fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "yay\'foo\'bar";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "yay\'foo\'bar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "yay\'foo\'bar";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "yayfoobar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foobar ";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "foo\ba\x6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobax6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "föo"));
+ free(t);
+ assert_se(p == original + 13);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "pi\360\237\222\251le"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "foo::bar";
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(p == original + 5);
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "bar"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "foo\\:bar::waldo";
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "foo:bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\ bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "\\w+@\\K[\\d.]+"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\\w+\\b";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "\\w+\b"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "-N ''";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "-N"));
+ free(t);
+ assert_se(p == original + 3);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = ":foo\\:bar::waldo:";
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 1);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "foo:bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 11);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(p == original + 17);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == NULL);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
+ assert_se(!t);
+ assert_se(!p);
+
+ p = "foo\\xbar";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "fooxbar"));
+ free(t);
+ assert_se(p == NULL);
+
+ p = "foo\\xbar";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) > 0);
+ assert_se(streq(t, "foo\\xbar"));
+ free(t);
+ assert_se(p == NULL);
+}
+
+static void test_extract_first_word_and_warn(void) {
+ const char *p, *original;
+ char *t;
+
+ p = original = "foobar waldo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 7);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo\ba\x6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobax6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "föo"));
+ free(t);
+ assert_se(p == original + 13);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "pi\360\237\222\251le"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\ bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "\\w+@\\K[\\d.]+"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\\w+\\b";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "\\w+\b"));
+ free(t);
+ assert_se(isempty(p));
+}
+
+static void test_extract_many_words(void) {
+ const char *p, *original;
+ char *a, *b, *c;
+
+ p = original = "foobar waldi piep";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ assert_se(streq_ptr(b, "waldi"));
+ assert_se(streq_ptr(c, "piep"));
+ free(a);
+ free(b);
+ free(c);
+
+ p = original = "'foobar' wa\"ld\"i ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "'foobar'"));
+ assert_se(streq_ptr(b, "wa\"ld\"i"));
+ assert_se(streq_ptr(c, NULL));
+ free(a);
+ free(b);
+
+ p = original = "'foobar' wa\"ld\"i ";
+ assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ assert_se(streq_ptr(b, "waldi"));
+ assert_se(streq_ptr(c, NULL));
+ free(a);
+ free(b);
+
+ p = original = "";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, NULL));
+ assert_se(streq_ptr(b, NULL));
+ assert_se(streq_ptr(c, NULL));
+
+ p = original = " ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, NULL));
+ assert_se(streq_ptr(b, NULL));
+ assert_se(streq_ptr(c, NULL));
+
+ p = original = "foobar";
+ assert_se(extract_many_words(&p, NULL, 0, NULL) == 0);
+ assert_se(p == original);
+
+ p = original = "foobar waldi";
+ assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
+ assert_se(p == original+7);
+ assert_se(streq_ptr(a, "foobar"));
+ free(a);
+
+ p = original = " foobar ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ free(a);
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_extract_first_word();
+ test_extract_first_word_and_warn();
+ test_extract_many_words();
+
+ return 0;
+}
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
new file mode 100644
index 0000000000..f555bb976c
--- /dev/null
+++ b/src/test/test-fd-util.c
@@ -0,0 +1,103 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+
+static void test_close_many(void) {
+ int fds[3];
+ char name0[] = "/tmp/test-close-many.XXXXXX";
+ char name1[] = "/tmp/test-close-many.XXXXXX";
+ char name2[] = "/tmp/test-close-many.XXXXXX";
+
+ fds[0] = mkostemp_safe(name0);
+ fds[1] = mkostemp_safe(name1);
+ fds[2] = mkostemp_safe(name2);
+
+ close_many(fds, 2);
+
+ assert_se(fcntl(fds[0], F_GETFD) == -1);
+ assert_se(fcntl(fds[1], F_GETFD) == -1);
+ assert_se(fcntl(fds[2], F_GETFD) >= 0);
+
+ safe_close(fds[2]);
+
+ unlink(name0);
+ unlink(name1);
+ unlink(name2);
+}
+
+static void test_close_nointr(void) {
+ char name[] = "/tmp/test-test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+ assert_se(close_nointr(fd) < 0);
+
+ unlink(name);
+}
+
+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);
+}
+
+int main(int argc, char *argv[]) {
+ test_close_many();
+ test_close_nointr();
+ test_same_fd();
+
+ return 0;
+}
diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c
index 242c5d9dc2..adbf99a7ec 100644
--- a/src/test/test-fdset.c
+++ b/src/test/test-fdset.c
@@ -20,16 +20,18 @@
#include <fcntl.h>
#include <unistd.h>
+#include "fd-util.h"
#include "fdset.h"
-#include "util.h"
+#include "fileio.h"
#include "macro.h"
+#include "util.h"
static void test_fdset_new_fill(void) {
int fd = -1;
_cleanup_fdset_free_ FDSet *fdset = NULL;
char name[] = "/tmp/test-fdset_new_fill.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(fdset_new_fill(&fdset) >= 0);
assert_se(fdset_contains(fdset, fd));
@@ -43,7 +45,7 @@ static void test_fdset_put_dup(void) {
_cleanup_fdset_free_ FDSet *fdset = NULL;
char name[] = "/tmp/test-fdset_put_dup.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -62,7 +64,7 @@ static void test_fdset_cloexec(void) {
int flags = -1;
char name[] = "/tmp/test-fdset_cloexec.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -89,7 +91,7 @@ static void test_fdset_close_others(void) {
int flags = -1;
char name[] = "/tmp/test-fdset_close_others.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -111,7 +113,7 @@ static void test_fdset_remove(void) {
FDSet *fdset = NULL;
char name[] = "/tmp/test-fdset_remove.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -134,7 +136,7 @@ static void test_fdset_iterate(void) {
int c = 0;
int a;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -159,7 +161,7 @@ static void test_fdset_isempty(void) {
_cleanup_fdset_free_ FDSet *fdset = NULL;
char name[] = "/tmp/test-fdset_isempty.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
@@ -177,7 +179,7 @@ static void test_fdset_steal_first(void) {
_cleanup_fdset_free_ FDSet *fdset = NULL;
char name[] = "/tmp/test-fdset_steal_first.XXXXXX";
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
fdset = fdset_new();
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index be3a87958f..92663ef66f 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,17 +17,22 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <fcntl.h>
+#include <stdio.h>
#include <unistd.h>
-#include "util.h"
-#include "process-util.h"
+#include "alloc-util.h"
+#include "ctype.h"
+#include "def.h"
+#include "env-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "string-util.h"
#include "strv.h"
-#include "env-util.h"
-#include "def.h"
-#include "ctype.h"
+#include "util.h"
static void test_parse_env_file(void) {
char t[] = "/tmp/test-fileio-in-XXXXXX",
@@ -42,11 +45,11 @@ static void test_parse_env_file(void) {
char **i;
unsigned k;
- fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(p);
assert_se(fd >= 0);
close(fd);
- fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(t);
assert_se(fd >= 0);
f = fdopen(fd, "w");
@@ -155,11 +158,11 @@ static void test_parse_multiline_env_file(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
char **i;
- fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(p);
assert_se(fd >= 0);
close(fd);
- fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(t);
assert_se(fd >= 0);
f = fdopen(fd, "w");
@@ -208,7 +211,7 @@ static void test_executable_is_script(void) {
FILE *f;
char *command;
- fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(t);
assert_se(fd >= 0);
f = fdopen(fd, "w");
@@ -241,18 +244,18 @@ static void test_status_field(void) {
unsigned long long total = 0, buffers = 0;
int r;
- assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
+ assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
puts(t);
assert_se(streq(t, "1"));
- r = get_status_field("/proc/meminfo", "MemTotal:", &p);
+ r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
if (r != -ENOENT) {
assert_se(r == 0);
puts(p);
assert_se(safe_atollu(p, &total) == 0);
}
- r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
+ r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
if (r != -ENOENT) {
assert_se(r == 0);
puts(s);
@@ -263,7 +266,7 @@ static void test_status_field(void) {
assert_se(buffers < total);
/* Seccomp should be a good test for field full of zeros. */
- r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
+ r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
if (r != -ENOENT) {
assert_se(r == 0);
puts(z);
@@ -286,7 +289,7 @@ static void test_capeff(void) {
assert_se(r == 0);
assert_se(*capeff);
- p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
+ p = capeff[strspn(capeff, HEXDIGITS)];
assert_se(!p || isspace(p));
}
}
@@ -297,7 +300,7 @@ static void test_write_string_stream(void) {
int fd;
char buf[64];
- fd = mkostemp_safe(fn, O_RDWR);
+ fd = mkostemp_safe(fn);
assert_se(fd >= 0);
f = fdopen(fd, "r");
@@ -331,7 +334,7 @@ static void test_write_string_file(void) {
char buf[64] = {};
_cleanup_close_ int fd;
- fd = mkostemp_safe(fn, O_RDWR);
+ fd = mkostemp_safe(fn);
assert_se(fd >= 0);
assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
@@ -347,7 +350,7 @@ static void test_write_string_file_no_create(void) {
_cleanup_close_ int fd;
char buf[64] = {0};
- fd = mkostemp_safe(fn, O_RDWR);
+ fd = mkostemp_safe(fn);
assert_se(fd >= 0);
assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
@@ -359,6 +362,26 @@ static void test_write_string_file_no_create(void) {
unlink(fn);
}
+static void test_write_string_file_verify(void) {
+ _cleanup_free_ char *buf = NULL, *buf2 = NULL;
+ int r;
+
+ assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
+ assert_se((buf2 = strjoin(buf, "\n", NULL)));
+
+ r = write_string_file("/proc/cmdline", buf, 0);
+ assert_se(r == -EACCES || r == -EIO);
+ r = write_string_file("/proc/cmdline", buf2, 0);
+ assert_se(r == -EACCES || r == -EIO);
+
+ assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
+ assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
+
+ r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE);
+ assert_se(r == -EACCES || r == -EIO);
+ assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
+}
+
static void test_load_env_file_pairs(void) {
char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
int fd;
@@ -367,7 +390,7 @@ static void test_load_env_file_pairs(void) {
_cleanup_strv_free_ char **l = NULL;
char **k, **v;
- fd = mkostemp_safe(fn, O_RDWR);
+ fd = mkostemp_safe(fn);
assert_se(fd >= 0);
r = write_string_file(fn,
@@ -403,6 +426,134 @@ static void test_load_env_file_pairs(void) {
unlink(fn);
}
+static void test_search_and_fopen(void) {
+ const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(basename(name), "r", "/", dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+
+static void test_search_and_fopen_nulstr(void) {
+ const char dirs[] = "/tmp/foo/bar\0/tmp\0";
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+static void test_writing_tmpfile(void) {
+ char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_free_ char *contents = NULL;
+ size_t size;
+ int fd, r;
+ struct iovec iov[3];
+
+ IOVEC_SET_STRING(iov[0], "abc\n");
+ IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
+ IOVEC_SET_STRING(iov[2], "");
+
+ fd = mkostemp_safe(name);
+ printf("tmpfile: %s", name);
+
+ r = writev(fd, iov, 3);
+ assert_se(r >= 0);
+
+ r = read_full_file(name, &contents, &size);
+ assert_se(r == 0);
+ printf("contents: %s", contents);
+ assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+
+ unlink(name);
+}
+
+static void test_tempfn(void) {
+ char *ret = NULL, *p;
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -415,7 +566,12 @@ int main(int argc, char *argv[]) {
test_write_string_stream();
test_write_string_file();
test_write_string_file_no_create();
+ test_write_string_file_verify();
test_load_env_file_pairs();
+ test_search_and_fopen();
+ test_search_and_fopen_nulstr();
+ test_writing_tmpfile();
+ test_tempfn();
return 0;
}
diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c
index d636e427c4..77e809c5bf 100644
--- a/src/test/test-firewall-util.c
+++ b/src/test/test-firewall-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
#include "firewall-util.h"
+#include "log.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))}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
new file mode 100644
index 0000000000..53a3cdc663
--- /dev/null
+++ b/src/test/test-fs-util.c
@@ -0,0 +1,243 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+static void test_chase_symlinks(void) {
+ _cleanup_free_ char *result = NULL;
+ char temp[] = "/tmp/test-chase.XXXXXX";
+ const char *top, *p, *q;
+ int r;
+
+ assert_se(mkdtemp(temp));
+
+ top = strjoina(temp, "/top");
+ assert_se(mkdir(top, 0700) >= 0);
+
+ p = strjoina(top, "/dot");
+ assert_se(symlink(".", p) >= 0);
+
+ p = strjoina(top, "/dotdot");
+ assert_se(symlink("..", p) >= 0);
+
+ p = strjoina(top, "/dotdota");
+ assert_se(symlink("../a", p) >= 0);
+
+ p = strjoina(temp, "/a");
+ assert_se(symlink("b", p) >= 0);
+
+ p = strjoina(temp, "/b");
+ assert_se(symlink("/usr", p) >= 0);
+
+ p = strjoina(temp, "/start");
+ assert_se(symlink("top/dot/dotdota", p) >= 0);
+
+ r = chase_symlinks(p, NULL, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, "/usr"));
+
+ result = mfree(result);
+ r = chase_symlinks(p, temp, &result);
+ assert_se(r == -ENOENT);
+
+ q = strjoina(temp, "/usr");
+ assert_se(mkdir(q, 0700) >= 0);
+
+ r = chase_symlinks(p, temp, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, q));
+
+ p = strjoina(temp, "/slash");
+ assert_se(symlink("/", p) >= 0);
+
+ result = mfree(result);
+ r = chase_symlinks(p, NULL, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, "/"));
+
+ result = mfree(result);
+ r = chase_symlinks(p, temp, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, temp));
+
+ p = strjoina(temp, "/slashslash");
+ assert_se(symlink("///usr///", p) >= 0);
+
+ result = mfree(result);
+ r = chase_symlinks(p, NULL, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, "/usr"));
+
+ result = mfree(result);
+ r = chase_symlinks(p, temp, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, q));
+
+ result = mfree(result);
+ r = chase_symlinks("/etc/./.././", NULL, &result);
+ assert_se(r >= 0);
+ assert_se(path_equal(result, "/"));
+
+ result = mfree(result);
+ r = chase_symlinks("/etc/./.././", "/etc", &result);
+ assert_se(r == -EINVAL);
+
+ result = mfree(result);
+ r = chase_symlinks("/etc/machine-id/foo", NULL, &result);
+ assert_se(r == -ENOTDIR);
+
+ result = mfree(result);
+ p = strjoina(temp, "/recursive-symlink");
+ assert_se(symlink("recursive-symlink", p) >= 0);
+ r = chase_symlinks(p, NULL, &result);
+ assert_se(r == -ELOOP);
+
+ assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+}
+
+static void test_unlink_noerrno(void) {
+ char name[] = "/tmp/test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+
+ {
+ PROTECT_ERRNO;
+ errno = -42;
+ assert_se(unlink_noerrno(name) >= 0);
+ assert_se(errno == -42);
+ assert_se(unlink_noerrno(name) < 0);
+ assert_se(errno == -42);
+ }
+}
+
+static void test_readlink_and_make_absolute(void) {
+ char tempdir[] = "/tmp/test-readlink_and_make_absolute";
+ char name[] = "/tmp/test-readlink_and_make_absolute/original";
+ char name2[] = "test-readlink_and_make_absolute/original";
+ char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
+ char *r = NULL;
+
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
+ assert_se(touch(name) >= 0);
+
+ assert_se(symlink(name, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(chdir(tempdir) >= 0);
+ assert_se(symlink(name2, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+}
+
+static void test_get_files_in_directory(void) {
+ _cleanup_strv_free_ char **l = NULL, **t = NULL;
+
+ assert_se(get_files_in_directory("/tmp", &l) >= 0);
+ assert_se(get_files_in_directory(".", &t) >= 0);
+ assert_se(get_files_in_directory(".", NULL) >= 0);
+}
+
+static void test_var_tmp(void) {
+ _cleanup_free_ char *tmpdir_backup = NULL, *temp_backup = NULL, *tmp_backup = NULL;
+ const char *tmp_dir = NULL, *t;
+
+ t = getenv("TMPDIR");
+ if (t) {
+ tmpdir_backup = strdup(t);
+ assert_se(tmpdir_backup);
+ }
+
+ t = getenv("TEMP");
+ if (t) {
+ temp_backup = strdup(t);
+ assert_se(temp_backup);
+ }
+
+ t = getenv("TMP");
+ if (t) {
+ tmp_backup = strdup(t);
+ assert_se(tmp_backup);
+ }
+
+ assert(unsetenv("TMPDIR") >= 0);
+ assert(unsetenv("TEMP") >= 0);
+ assert(unsetenv("TMP") >= 0);
+
+ assert_se(var_tmp_dir(&tmp_dir) >= 0);
+ assert_se(streq(tmp_dir, "/var/tmp"));
+
+ assert_se(setenv("TMPDIR", "/tmp", true) >= 0);
+ assert_se(streq(getenv("TMPDIR"), "/tmp"));
+
+ assert_se(var_tmp_dir(&tmp_dir) >= 0);
+ assert_se(streq(tmp_dir, "/tmp"));
+
+ assert_se(setenv("TMPDIR", "/88_does_not_exist_88", true) >= 0);
+ assert_se(streq(getenv("TMPDIR"), "/88_does_not_exist_88"));
+
+ assert_se(var_tmp_dir(&tmp_dir) >= 0);
+ assert_se(streq(tmp_dir, "/var/tmp"));
+
+ if (tmpdir_backup) {
+ assert_se(setenv("TMPDIR", tmpdir_backup, true) >= 0);
+ assert_se(streq(getenv("TMPDIR"), tmpdir_backup));
+ }
+
+ if (temp_backup) {
+ assert_se(setenv("TEMP", temp_backup, true) >= 0);
+ assert_se(streq(getenv("TEMP"), temp_backup));
+ }
+
+ if (tmp_backup) {
+ assert_se(setenv("TMP", tmp_backup, true) >= 0);
+ assert_se(streq(getenv("TMP"), tmp_backup));
+ }
+}
+
+int main(int argc, char *argv[]) {
+ test_unlink_noerrno();
+ test_readlink_and_make_absolute();
+ test_get_files_in_directory();
+ test_var_tmp();
+ test_chase_symlinks();
+
+ return 0;
+}
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index 50e5dee0a7..63a4b8c243 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,9 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "fstab-util.h"
-#include "util.h"
#include "log.h"
+#include "string-util.h"
+#include "util.h"
/*
int fstab_filter_options(const char *opts, const char *names,
@@ -131,8 +131,45 @@ static void test_fstab_yes_no_option(void) {
assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false);
}
+static void test_fstab_node_to_udev_node(void) {
+ char *n;
+
+ n = fstab_node_to_udev_node("LABEL=applé/jack");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
+ free(n);
+
+ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PONIES=awesome");
+ puts(n);
+ assert_se(streq(n, "PONIES=awesome"));
+ free(n);
+
+ n = fstab_node_to_udev_node("/dev/xda1");
+ puts(n);
+ assert_se(streq(n, "/dev/xda1"));
+ free(n);
+}
+
int main(void) {
test_fstab_filter_options();
test_fstab_find_pri();
test_fstab_yes_no_option();
+ test_fstab_node_to_udev_node();
+
+ return 0;
}
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
new file mode 100644
index 0000000000..9eea3eb608
--- /dev/null
+++ b/src/test/test-glob-util.c
@@ -0,0 +1,50 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "glob-util.h"
+#include "macro.h"
+
+static void test_glob_exists(void) {
+ char name[] = "/tmp/test-glob_exists.XXXXXX";
+ int fd = -1;
+ int r;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 1);
+
+ r = unlink(name);
+ assert_se(r == 0);
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 0);
+}
+
+int main(void) {
+ test_glob_exists();
+
+ return 0;
+}
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 057b6c1dc1..1bd5c02f87 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -17,9 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "hashmap.h"
+#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "hashmap.h"
void test_hashmap_funcs(void);
@@ -321,26 +323,29 @@ static void test_hashmap_remove_value(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
char *r;
- r = hashmap_remove_value(NULL, "key 1", (void*) "val 1");
+ char val1[] = "val 1";
+ char val2[] = "val 2";
+
+ r = hashmap_remove_value(NULL, "key 1", val1);
assert_se(r == NULL);
m = hashmap_new(&string_hash_ops);
assert_se(m);
- r = hashmap_remove_value(m, "key 1", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 1", val1);
assert_se(r == NULL);
- hashmap_put(m, "key 1", (void*) "val 1");
- hashmap_put(m, "key 2", (void*) "val 2");
+ hashmap_put(m, "key 1", val1);
+ hashmap_put(m, "key 2", val2);
- r = hashmap_remove_value(m, "key 1", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 1", val1);
assert_se(streq(r, "val 1"));
r = hashmap_get(m, "key 2");
assert_se(streq(r, "val 2"));
assert_se(!hashmap_get(m, "key 1"));
- r = hashmap_remove_value(m, "key 2", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 2", val1);
assert_se(r == NULL);
r = hashmap_get(m, "key 2");
@@ -692,8 +697,8 @@ static void test_hashmap_get2(void) {
hashmap_free_free_free(m);
}
-static unsigned long crippled_hashmap_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- return trivial_hash_func(p, hash_key) & 0xff;
+static void crippled_hashmap_func(const void *p, struct siphash *state) {
+ return trivial_hash_func(INT_TO_PTR(PTR_TO_INT(p) & 0xff), state);
}
static const struct hash_ops crippled_hashmap_ops = {
@@ -710,7 +715,7 @@ static void test_hashmap_many(void) {
unsigned n_entries;
} tests[] = {
{ .ops = NULL, .n_entries = 1 << 20 },
- { .ops = &crippled_hashmap_ops, .n_entries = 1 << 11 },
+ { .ops = &crippled_hashmap_ops, .n_entries = 1 << 14 },
};
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index d0e65001f5..83cea360e6 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -17,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "hashmap.h"
+#include "util.h"
void test_hashmap_funcs(void);
void test_ordered_hashmap_funcs(void);
diff --git a/src/test/test-helper.h b/src/test/test-helper.h
index f75dd3374a..ddb10f88fd 100644
--- a/src/test/test-helper.h
+++ b/src/test/test-helper.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -23,9 +21,21 @@
#include "sd-daemon.h"
+#include "macro.h"
+
#define TEST_REQ_RUNNING_SYSTEMD(x) \
if (sd_booted() > 0) { \
x; \
} else { \
printf("systemd not booted skipping '%s'\n", #x); \
}
+
+#define MANAGER_SKIP_TEST(r) \
+ IN_SET(r, \
+ -EPERM, \
+ -EACCES, \
+ -EADDRINUSE, \
+ -EHOSTDOWN, \
+ -ENOENT, \
+ -ENOMEDIUM /* cannot determine cgroup */ \
+ )
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
new file mode 100644
index 0000000000..276f25d091
--- /dev/null
+++ b/src/test/test-hexdecoct.c
@@ -0,0 +1,387 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "alloc-util.h"
+#include "hexdecoct.h"
+#include "macro.h"
+#include "string-util.h"
+
+static void test_hexchar(void) {
+ assert_se(hexchar(0xa) == 'a');
+ assert_se(hexchar(0x0) == '0');
+}
+
+static void test_unhexchar(void) {
+ assert_se(unhexchar('a') == 0xA);
+ assert_se(unhexchar('A') == 0xA);
+ assert_se(unhexchar('0') == 0x0);
+}
+
+static void test_base32hexchar(void) {
+ assert_se(base32hexchar(0) == '0');
+ assert_se(base32hexchar(9) == '9');
+ assert_se(base32hexchar(10) == 'A');
+ assert_se(base32hexchar(31) == 'V');
+}
+
+static void test_unbase32hexchar(void) {
+ assert_se(unbase32hexchar('0') == 0);
+ assert_se(unbase32hexchar('9') == 9);
+ assert_se(unbase32hexchar('A') == 10);
+ assert_se(unbase32hexchar('V') == 31);
+ assert_se(unbase32hexchar('=') == -EINVAL);
+}
+
+static void test_base64char(void) {
+ assert_se(base64char(0) == 'A');
+ assert_se(base64char(26) == 'a');
+ assert_se(base64char(63) == '/');
+}
+
+static void test_unbase64char(void) {
+ assert_se(unbase64char('A') == 0);
+ assert_se(unbase64char('Z') == 25);
+ assert_se(unbase64char('a') == 26);
+ assert_se(unbase64char('z') == 51);
+ assert_se(unbase64char('0') == 52);
+ assert_se(unbase64char('9') == 61);
+ assert_se(unbase64char('+') == 62);
+ assert_se(unbase64char('/') == 63);
+ assert_se(unbase64char('=') == -EINVAL);
+}
+
+static void test_octchar(void) {
+ assert_se(octchar(00) == '0');
+ assert_se(octchar(07) == '7');
+}
+
+static void test_unoctchar(void) {
+ assert_se(unoctchar('0') == 00);
+ assert_se(unoctchar('7') == 07);
+}
+
+static void test_decchar(void) {
+ assert_se(decchar(0) == '0');
+ assert_se(decchar(9) == '9');
+}
+
+static void test_undecchar(void) {
+ assert_se(undecchar('0') == 0);
+ assert_se(undecchar('9') == 9);
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base32hexmem(void) {
+ char *b32;
+
+ b32 = base32hexmem("", strlen(""), true);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CO======"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG===="));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU==="));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG="));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8======"));
+ free(b32);
+
+ b32 = base32hexmem("", strlen(""), false);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CO"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG"));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU"));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG"));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8"));
+ free(b32);
+}
+
+static void test_unbase32hexmem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base64mem(void) {
+ char *b64;
+
+ assert_se(base64mem("", strlen(""), &b64) == 0);
+ assert_se(streq(b64, ""));
+ free(b64);
+
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
+ assert_se(streq(b64, "Zg=="));
+ free(b64);
+
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
+ assert_se(streq(b64, "Zm8="));
+ free(b64);
+
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
+ assert_se(streq(b64, "Zm9v"));
+ free(b64);
+
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYg=="));
+ free(b64);
+
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmE="));
+ free(b64);
+
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmFy"));
+ free(b64);
+}
+
+static void test_unbase64mem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+}
+
+static void test_hexdump(void) {
+ uint8_t data[146];
+ unsigned i;
+
+ hexdump(stdout, NULL, 0);
+ hexdump(stdout, "", 0);
+ hexdump(stdout, "", 1);
+ hexdump(stdout, "x", 1);
+ hexdump(stdout, "x", 2);
+ hexdump(stdout, "foobar", 7);
+ hexdump(stdout, "f\nobar", 7);
+ hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
+
+ for (i = 0; i < ELEMENTSOF(data); i++)
+ data[i] = i*2;
+
+ hexdump(stdout, data, sizeof(data));
+}
+
+int main(int argc, char *argv[]) {
+ test_hexchar();
+ test_unhexchar();
+ test_base32hexchar();
+ test_unbase32hexchar();
+ test_base64char();
+ test_unbase64char();
+ test_octchar();
+ test_unoctchar();
+ test_decchar();
+ test_undecchar();
+ test_unhexmem();
+ test_base32hexmem();
+ test_unbase32hexmem();
+ test_base64mem();
+ test_unbase64mem();
+ test_hexdump();
+
+ return 0;
+}
diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c
new file mode 100644
index 0000000000..d2c3ea5e0d
--- /dev/null
+++ b/src/test/test-hostname-util.c
@@ -0,0 +1,160 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2013 Thomas H.P. Andersen
+ 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 "alloc-util.h"
+#include "fileio.h"
+#include "hostname-util.h"
+#include "string-util.h"
+#include "util.h"
+
+static void test_hostname_is_valid(void) {
+ assert_se(hostname_is_valid("foobar", false));
+ assert_se(hostname_is_valid("foobar.com", false));
+ assert_se(!hostname_is_valid("foobar.com.", false));
+ assert_se(hostname_is_valid("fooBAR", false));
+ assert_se(hostname_is_valid("fooBAR.com", false));
+ assert_se(!hostname_is_valid("fooBAR.", false));
+ assert_se(!hostname_is_valid("fooBAR.com.", false));
+ assert_se(!hostname_is_valid("fööbar", false));
+ assert_se(!hostname_is_valid("", false));
+ assert_se(!hostname_is_valid(".", false));
+ assert_se(!hostname_is_valid("..", false));
+ assert_se(!hostname_is_valid("foobar.", false));
+ assert_se(!hostname_is_valid(".foobar", false));
+ assert_se(!hostname_is_valid("foo..bar", false));
+ assert_se(!hostname_is_valid("foo.bar..", false));
+ assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", false));
+ assert_se(!hostname_is_valid("au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local", false));
+
+ assert_se(hostname_is_valid("foobar", true));
+ assert_se(hostname_is_valid("foobar.com", true));
+ assert_se(hostname_is_valid("foobar.com.", true));
+ assert_se(hostname_is_valid("fooBAR", true));
+ assert_se(hostname_is_valid("fooBAR.com", true));
+ assert_se(!hostname_is_valid("fooBAR.", true));
+ assert_se(hostname_is_valid("fooBAR.com.", true));
+ assert_se(!hostname_is_valid("fööbar", true));
+ assert_se(!hostname_is_valid("", true));
+ assert_se(!hostname_is_valid(".", true));
+ assert_se(!hostname_is_valid("..", true));
+ assert_se(!hostname_is_valid("foobar.", true));
+ assert_se(!hostname_is_valid(".foobar", true));
+ assert_se(!hostname_is_valid("foo..bar", true));
+ assert_se(!hostname_is_valid("foo.bar..", true));
+ assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true));
+}
+
+static void test_hostname_cleanup(void) {
+ char *s;
+
+ s = strdupa("foobar");
+ assert_se(streq(hostname_cleanup(s), "foobar"));
+ s = strdupa("foobar.com");
+ assert_se(streq(hostname_cleanup(s), "foobar.com"));
+ s = strdupa("foobar.com.");
+ assert_se(streq(hostname_cleanup(s), "foobar.com"));
+ s = strdupa("fooBAR");
+ assert_se(streq(hostname_cleanup(s), "fooBAR"));
+ s = strdupa("fooBAR.com");
+ assert_se(streq(hostname_cleanup(s), "fooBAR.com"));
+ s = strdupa("fooBAR.");
+ assert_se(streq(hostname_cleanup(s), "fooBAR"));
+ s = strdupa("fooBAR.com.");
+ assert_se(streq(hostname_cleanup(s), "fooBAR.com"));
+ s = strdupa("fööbar");
+ assert_se(streq(hostname_cleanup(s), "fbar"));
+ s = strdupa("");
+ assert_se(isempty(hostname_cleanup(s)));
+ s = strdupa(".");
+ assert_se(isempty(hostname_cleanup(s)));
+ s = strdupa("..");
+ assert_se(isempty(hostname_cleanup(s)));
+ s = strdupa("foobar.");
+ assert_se(streq(hostname_cleanup(s), "foobar"));
+ s = strdupa(".foobar");
+ assert_se(streq(hostname_cleanup(s), "foobar"));
+ s = strdupa("foo..bar");
+ assert_se(streq(hostname_cleanup(s), "foo.bar"));
+ s = strdupa("foo.bar..");
+ assert_se(streq(hostname_cleanup(s), "foo.bar"));
+ s = strdupa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+ assert_se(streq(hostname_cleanup(s), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
+}
+
+static void test_read_hostname_config(void) {
+ char path[] = "/tmp/hostname.XXXXXX";
+ char *hostname;
+ int fd;
+
+ fd = mkostemp_safe(path);
+ assert(fd > 0);
+ close(fd);
+
+ /* simple hostname */
+ write_string_file(path, "foo", WRITE_STRING_FILE_CREATE);
+ assert_se(read_hostname_config(path, &hostname) == 0);
+ assert_se(streq(hostname, "foo"));
+ hostname = mfree(hostname);
+
+ /* with comment */
+ write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE);
+ assert_se(read_hostname_config(path, &hostname) == 0);
+ assert_se(hostname);
+ assert_se(streq(hostname, "foo"));
+ hostname = mfree(hostname);
+
+ /* with comment and extra whitespace */
+ write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE);
+ assert_se(read_hostname_config(path, &hostname) == 0);
+ assert_se(hostname);
+ assert_se(streq(hostname, "foo"));
+ hostname = mfree(hostname);
+
+ /* cleans up name */
+ write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE);
+ assert_se(read_hostname_config(path, &hostname) == 0);
+ assert_se(hostname);
+ assert_se(streq(hostname, "foobar.com"));
+ hostname = mfree(hostname);
+
+ /* no value set */
+ hostname = (char*) 0x1234;
+ write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE);
+ assert_se(read_hostname_config(path, &hostname) == -ENOENT);
+ assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
+
+ /* nonexisting file */
+ assert_se(read_hostname_config("/non/existing", &hostname) == -ENOENT);
+ assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
+
+ unlink(path);
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_hostname_is_valid();
+ test_hostname_cleanup();
+ test_read_hostname_config();
+
+ return 0;
+}
diff --git a/src/test/test-hostname.c b/src/test/test-hostname.c
index dd50c5148c..b38507df5d 100644
--- a/src/test/test-hostname.c
+++ b/src/test/test-hostname.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index a6a0cd77a1..1c8e5549da 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,11 +19,16 @@
#include <string.h>
-#include "systemd/sd-id128.h"
+#include "sd-daemon.h"
+#include "sd-id128.h"
-#include "util.h"
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "id128-util.h"
#include "macro.h"
-#include "sd-daemon.h"
+#include "string-util.h"
+#include "util.h"
#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
#define STR_WALDI "0102030405060708090a0b0c0d0e0f10"
@@ -33,8 +36,9 @@
int main(int argc, char *argv[]) {
sd_id128_t id, id2;
- char t[33];
+ char t[33], q[37];
_cleanup_free_ char *b = NULL;
+ _cleanup_close_ int fd = -1;
assert_se(sd_id128_randomize(&id) == 0);
printf("random: %s\n", sd_id128_to_string(id, t));
@@ -57,6 +61,17 @@ int main(int argc, char *argv[]) {
printf("waldi2: %s\n", b);
assert_se(streq(t, b));
+ printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q));
+ assert_se(streq(q, UUID_WALDI));
+
+ b = mfree(b);
+ assert_se(asprintf(&b, ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36);
+ printf("waldi4: %s\n", b);
+ assert_se(streq(q, b));
+
+ assert_se(sd_id128_from_string(STR_WALDI, &id) >= 0);
+ assert_se(sd_id128_equal(id, ID128_WALDI));
+
assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0);
assert_se(sd_id128_equal(id, ID128_WALDI));
@@ -74,5 +89,69 @@ int main(int argc, char *argv[]) {
assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10"));
assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10"));
+ fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+
+ /* First, write as UUID */
+ assert_se(sd_id128_randomize(&id) >= 0);
+ assert_se(id128_write_fd(fd, ID128_UUID, id, false) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
+ /* Second, write as plain */
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+
+ assert_se(sd_id128_randomize(&id) >= 0);
+ assert_se(id128_write_fd(fd, ID128_PLAIN, id, false) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
+ /* Third, write plain without trailing newline */
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+
+ assert_se(sd_id128_randomize(&id) >= 0);
+ assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
+ /* Third, write UUID without trailing newline */
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+
+ assert_se(sd_id128_randomize(&id) >= 0);
+ assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+
return 0;
}
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
new file mode 100644
index 0000000000..db1c928660
--- /dev/null
+++ b/src/test/test-install-root.c
@@ -0,0 +1,770 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2011 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 "alloc-util.h"
+#include "fileio.h"
+#include "install.h"
+#include "mkdir.h"
+#include "rm-rf.h"
+#include "string-util.h"
+
+static void test_basic_mask_and_enable(const char *root) {
+ const char *p;
+ UnitFileState state;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+
+ log_set_max_level(LOG_DEBUG);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/a.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/b.service");
+ assert_se(symlink("a.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/c.service");
+ assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system/d.service");
+ assert_se(symlink("c.service", p) >= 0);
+
+ /* This one is interesting, as d follows a relative, then an absolute symlink */
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/dev/null"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
+ assert_se(streq(changes[0].path, p));
+
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
+
+ /* Enabling a masked unit should fail! */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ERFKILL);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* Enabling it again should succeed but be a NOP */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ /* Disabling a disabled unit must suceed but be a NOP */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ /* Let's enable this indirectly via a symlink */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* Let's try to reenable */
+
+ assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
+ assert_se(streq(changes[0].path, p));
+ assert_se(changes[1].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
+ assert_se(streq(changes[1].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+}
+
+static void test_linked_units(const char *root) {
+ const char *p, *q;
+ UnitFileState state;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0, i;
+
+ /*
+ * We'll test three cases here:
+ *
+ * a) a unit file in /opt, that we use "systemctl link" and
+ * "systemctl enable" on to make it available to the system
+ *
+ * b) a unit file in /opt, that is statically linked into
+ * /usr/lib/systemd/system, that "enable" should work on
+ * correctly.
+ *
+ * c) a unit file in /opt, that is linked into
+ * /etc/systemd/system, and where "enable" should result in
+ * -ELOOP, since using information from /etc to generate
+ * information in /etc should not be allowed.
+ */
+
+ p = strjoina(root, "/opt/linked.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/opt/linked2.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/opt/linked3.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
+ assert_se(symlink("/opt/linked2.service", p) >= 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
+ assert_se(symlink("/opt/linked3.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
+
+ /* First, let's link the unit into the search path */
+ assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/opt/linked.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
+
+ /* Let's unlink it from the search path again */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+
+ /* Now, let's not just link it, but also enable it */
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ for (i = 0 ; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[i].source, "/opt/linked.service"));
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* And let's unlink it again */
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
+ for (i = 0; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_UNLINK);
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
+ q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
+ for (i = 0 ; i < n_changes; i++) {
+ assert_se(changes[i].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[i].source, "/opt/linked2.service"));
+
+ if (p && streq(changes[i].path, p))
+ p = NULL;
+ else if (q && streq(changes[i].path, q))
+ q = NULL;
+ else
+ assert_not_reached("wut?");
+ }
+ assert(!p && !q);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(startswith(changes[0].path, root));
+ assert_se(endswith(changes[0].path, "linked3.service"));
+ assert_se(streq(changes[0].source, "/opt/linked3.service"));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_default(const char *root) {
+ _cleanup_free_ char *def = NULL;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ const char *p;
+
+ p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
+ assert_se(symlink("test-default-real.target", p) >= 0);
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
+
+ assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
+
+ assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
+ assert_se(streq_ptr(def, "test-default-real.target"));
+}
+
+static void test_add_dependency(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ const char *p;
+
+ p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
+ assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
+ assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
+
+ assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_template_enable(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ UnitFileState state;
+ const char *p;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/template@.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "DefaultInstance=def\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
+ assert_se(symlink("template@.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+}
+
+static void test_indirect(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ UnitFileState state;
+ const char *p;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
+ assert_se(symlink("indirecta.service", p) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_preset_and_list(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0, i;
+ const char *p, *q;
+ UnitFileState state;
+ bool got_yes = false, got_no = false;
+ Iterator j;
+ UnitFileList *fl;
+ Hashmap *h;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
+ assert_se(write_string_file(p,
+ "enable *-yes.*\n"
+ "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+
+ assert_se(n_changes > 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
+
+ for (i = 0; i < n_changes; i++) {
+
+ if (changes[i].type == UNIT_FILE_SYMLINK) {
+ assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
+ assert_se(streq(changes[i].path, p));
+ } else
+ assert_se(changes[i].type == UNIT_FILE_UNLINK);
+ }
+
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(h = hashmap_new(&string_hash_ops));
+ assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
+ q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
+
+ HASHMAP_FOREACH(fl, h, j) {
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
+ assert_se(fl->state == state);
+
+ if (streq(fl->path, p)) {
+ got_yes = true;
+ assert_se(fl->state == UNIT_FILE_ENABLED);
+ } else if (streq(fl->path, q)) {
+ got_no = true;
+ assert_se(fl->state == UNIT_FILE_DISABLED);
+ } else
+ assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
+ }
+
+ unit_file_list_free(h);
+
+ assert_se(got_yes && got_no);
+}
+
+static void test_revert(const char *root) {
+ const char *p;
+ UnitFileState state;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+
+ assert(root);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/xx.service");
+ assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC);
+
+ /* Initially there's nothing to revert */
+ assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service");
+ assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ /* Revert the override file */
+ assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf");
+ assert_se(mkdir_parents(p, 0755) >= 0);
+ assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ /* Revert the dropin file */
+ assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
+ assert_se(n_changes == 2);
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[0].path, p));
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d");
+ assert_se(changes[1].type == UNIT_FILE_UNLINK);
+ assert_se(streq(changes[1].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+}
+
+static void test_preset_order(const char *root) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ const char *p;
+ UnitFileState state;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT);
+
+ p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
+ assert_se(write_string_file(p,
+ "enable prefix-1.service\n"
+ "disable prefix-*.service\n"
+ "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
+ assert_se(n_changes == 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+}
+
+int main(int argc, char *argv[]) {
+ char root[] = "/tmp/rootXXXXXX";
+ const char *p;
+
+ assert_se(mkdtemp(root));
+
+ p = strjoina(root, "/usr/lib/systemd/system/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/run/systemd/system/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/opt/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/");
+ assert_se(mkdir_p(p, 0755) >= 0);
+
+ test_basic_mask_and_enable(root);
+ test_linked_units(root);
+ test_default(root);
+ test_add_dependency(root);
+ test_template_enable(root);
+ test_indirect(root);
+ test_preset_and_list(root);
+ test_preset_order(root);
+ test_revert(root);
+
+ assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+
+ return 0;
+}
diff --git a/src/test/test-install.c b/src/test/test-install.c
index 5ee52e64cb..0ac85f040a 100644
--- a/src/test/test-install.c
+++ b/src/test/test-install.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "install.h"
@@ -46,17 +44,22 @@ int main(int argc, char* argv[]) {
const char *const files2[] = { "/home/lennart/test.service", NULL };
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
+ UnitFileState state = 0;
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
h = hashmap_new(&string_hash_ops);
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
assert_se(r == 0);
HASHMAP_FOREACH(p, h, i) {
- UnitFileState s;
+ UnitFileState s = _UNIT_FILE_STATE_INVALID;
- s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path));
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s);
- assert_se(p->state == s);
+ assert_se((r < 0 && p->state == UNIT_FILE_BAD) ||
+ (p->state == s));
fprintf(stderr, "%s (%s)\n",
p->path,
@@ -65,12 +68,12 @@ int main(int argc, char* argv[]) {
unit_file_list_free(h);
- log_error("enable");
+ log_info("/*** enable **/");
r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
- log_error("enable2");
+ log_info("/*** enable2 **/");
r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
@@ -78,10 +81,11 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_ENABLED);
-
- log_error("disable");
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
+ log_info("/*** disable ***/");
changes = NULL;
n_changes = 0;
@@ -91,39 +95,45 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
- log_error("mask");
+ log_info("/*** mask ***/");
changes = NULL;
n_changes = 0;
r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
- log_error("mask2");
+ log_info("/*** mask2 ***/");
r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
- log_error("unmask");
+ log_info("/*** unmask ***/");
changes = NULL;
n_changes = 0;
r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
assert_se(r >= 0);
- log_error("unmask2");
+ log_info("/*** unmask2 ***/");
r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
- log_error("mask");
+ log_info("/*** mask ***/");
changes = NULL;
n_changes = 0;
@@ -133,24 +143,28 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
- log_error("disable");
+ log_info("/*** disable ***/");
changes = NULL;
n_changes = 0;
r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
assert_se(r >= 0);
- log_error("disable2");
+ log_info("/*** disable2 ***/");
r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_MASKED);
- log_error("umask");
+ log_info("/*** umask ***/");
changes = NULL;
n_changes = 0;
@@ -160,9 +174,11 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_DISABLED);
- log_error("enable files2");
+ log_info("/*** enable files2 ***/");
changes = NULL;
n_changes = 0;
@@ -172,21 +188,24 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
- log_error("disable files2");
+ log_info("/*** disable files2 ***/");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
- log_error("link files2");
+ log_info("/*** link files2 ***/");
changes = NULL;
n_changes = 0;
@@ -196,21 +215,24 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_LINKED);
- log_error("disable files2");
+ log_info("/*** disable files2 ***/");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
- log_error("link files2");
+ log_info("/*** link files2 ***/");
changes = NULL;
n_changes = 0;
@@ -220,9 +242,11 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_LINKED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_LINKED);
- log_error("reenable files2");
+ log_info("/*** reenable files2 ***/");
changes = NULL;
n_changes = 0;
@@ -232,20 +256,23 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
- log_error("disable files2");
+ log_info("/*** disable files2 ***/");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
- log_error("preset files");
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
+ assert_se(r < 0);
+ log_info("/*** preset files ***/");
changes = NULL;
n_changes = 0;
@@ -255,7 +282,9 @@ int main(int argc, char* argv[]) {
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0])) == UNIT_FILE_ENABLED);
+ r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state);
+ assert_se(r >= 0);
+ assert_se(state == UNIT_FILE_ENABLED);
return 0;
}
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
new file mode 100644
index 0000000000..10bd3833bc
--- /dev/null
+++ b/src/test/test-io-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "macro.h"
+
+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(void) {
+ test_sparse_write();
+
+ return 0;
+}
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 4944bf6ad9..551eba7215 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,14 +17,20 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "clean-ipc.h"
+#include "user-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
uid_t uid;
+ int r;
+ const char* name = argv[1] ?: "nfsnobody";
- assert_se(argc == 2);
- assert_se(parse_uid(argv[1], &uid) >= 0);
+ r = get_user_creds(&name, &uid, NULL, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to resolve \"%s\": %m", name);
+ return EXIT_FAILURE;
+ }
- return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return clean_ipc_by_uid(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c
index af0d76e894..7f0b9f253c 100644
--- a/src/test/test-job-type.c
+++ b/src/test/test-job-type.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,8 +20,8 @@
#include <stdio.h>
#include "job.h"
-#include "unit.h"
#include "service.h"
+#include "unit.h"
int main(int argc, char*argv[]) {
JobType a, b, c, ab, bc, ab_c, bc_a, a_bc;
diff --git a/src/test/test-json.c b/src/test/test-json.c
deleted file mode 100644
index 1058c583c3..0000000000
--- a/src/test/test-json.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-*- 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 "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);
-}
-
-typedef void (*Test)(JsonVariant *);
-
-static void test_file(const char *data, Test test) {
- _cleanup_json_variant_unref_ JsonVariant *v = NULL;
- int r;
-
- r = json_parse(data, &v);
- assert_se(r == 0);
- assert_se(v != NULL);
- assert_se(v->type == JSON_VARIANT_OBJECT);
-
- if (test)
- test(v);
-}
-
-static void test_1(JsonVariant *v) {
- JsonVariant *p, *q;
- unsigned i;
-
- /* 3 keys + 3 values */
- assert_se(v->size == 6);
-
- /* has k */
- p = json_variant_value(v, "k");
- assert_se(p && p->type == JSON_VARIANT_STRING);
-
- /* k equals v */
- assert_se(streq(json_variant_string(p), "v"));
-
- /* has foo */
- p = json_variant_value(v, "foo");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 3);
-
- /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */
- for (i = 0; i < 3; ++i) {
- q = json_variant_element(p, i);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == (i+1));
- }
-
- /* has bar */
- p = json_variant_value(v, "bar");
- assert_se(p && p->type == JSON_VARIANT_OBJECT && p->size == 2);
-
- /* zap is null */
- q = json_variant_value(p, "zap");
- assert_se(q && q->type == JSON_VARIANT_NULL);
-}
-
-static void test_2(JsonVariant *v) {
- JsonVariant *p, *q;
-
- /* 2 keys + 2 values */
- assert_se(v->size == 4);
-
- /* has mutant */
- p = json_variant_value(v, "mutant");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 4);
-
- /* mutant[0] == 1 */
- q = json_variant_element(p, 0);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
-
- /* mutant[1] == null */
- q = json_variant_element(p, 1);
- assert_se(q && q->type == JSON_VARIANT_NULL);
-
- /* mutant[2] == "1" */
- q = json_variant_element(p, 2);
- assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
-
- /* mutant[3] == JSON_VARIANT_OBJECT */
- q = json_variant_element(p, 3);
- assert_se(q && q->type == JSON_VARIANT_OBJECT && q->size == 2);
-
- /* has 1 */
- p = json_variant_value(q, "1");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 2);
-
- /* "1"[0] == 1 */
- q = json_variant_element(p, 0);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
-
- /* "1"[1] == "1" */
- q = json_variant_element(p, 1);
- assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
-
- /* has blah */
- p = json_variant_value(v, "blah");
- assert_se(p && p->type == JSON_VARIANT_REAL && fabs(json_variant_real(p) - 1.27) < 0.001);
-}
-
-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);
-
- test_one("[1, 2]", JSON_ARRAY_OPEN, JSON_INTEGER, (intmax_t) 1, JSON_COMMA, JSON_INTEGER, (intmax_t) 2, JSON_ARRAY_CLOSE, JSON_END);
-
- test_file("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1);
- test_file("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"blah\": 1.27}", test_2);
-
- return 0;
-}
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index 34c49b969a..e28de9b37b 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -1,4 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
@@ -18,174 +17,147 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
-#include <unistd.h>
#include <getopt.h>
+#include <stdio.h>
#include <sys/epoll.h>
+#include <unistd.h>
#include "libudev.h"
+
+#include "fd-util.h"
+#include "log.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "udev-util.h"
#include "util.h"
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
static void print_device(struct udev_device *device) {
const char *str;
dev_t devnum;
int count;
struct udev_list_entry *list_entry;
- printf("*** device: %p ***\n", device);
+ log_info("*** device: %p ***", device);
str = udev_device_get_action(device);
if (str != NULL)
- printf("action: '%s'\n", str);
+ log_info("action: '%s'", str);
str = udev_device_get_syspath(device);
- printf("syspath: '%s'\n", str);
+ log_info("syspath: '%s'", str);
str = udev_device_get_sysname(device);
- printf("sysname: '%s'\n", str);
+ log_info("sysname: '%s'", str);
str = udev_device_get_sysnum(device);
if (str != NULL)
- printf("sysnum: '%s'\n", str);
+ log_info("sysnum: '%s'", str);
str = udev_device_get_devpath(device);
- printf("devpath: '%s'\n", str);
+ log_info("devpath: '%s'", str);
str = udev_device_get_subsystem(device);
if (str != NULL)
- printf("subsystem: '%s'\n", str);
+ log_info("subsystem: '%s'", str);
str = udev_device_get_devtype(device);
if (str != NULL)
- printf("devtype: '%s'\n", str);
+ log_info("devtype: '%s'", str);
str = udev_device_get_driver(device);
if (str != NULL)
- printf("driver: '%s'\n", str);
+ log_info("driver: '%s'", str);
str = udev_device_get_devnode(device);
if (str != NULL)
- printf("devname: '%s'\n", str);
+ log_info("devname: '%s'", str);
devnum = udev_device_get_devnum(device);
if (major(devnum) > 0)
- printf("devnum: %u:%u\n", major(devnum), minor(devnum));
+ log_info("devnum: %u:%u", major(devnum), minor(devnum));
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
- printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
+ log_info("link: '%s'", udev_list_entry_get_name(list_entry));
count++;
}
if (count > 0)
- printf("found %i links\n", count);
+ log_info("found %i links", count);
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
- printf("property: '%s=%s'\n",
+ log_info("property: '%s=%s'",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
count++;
}
if (count > 0)
- printf("found %i properties\n", count);
+ log_info("found %i properties", count);
str = udev_device_get_property_value(device, "MAJOR");
if (str != NULL)
- printf("MAJOR: '%s'\n", str);
+ log_info("MAJOR: '%s'", str);
str = udev_device_get_sysattr_value(device, "dev");
if (str != NULL)
- printf("attr{dev}: '%s'\n", str);
-
- printf("\n");
+ log_info("attr{dev}: '%s'", str);
}
-static int test_device(struct udev *udev, const char *syspath) {
+static void test_device(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
- if (device == NULL) {
- printf("no device found\n");
- return -1;
- }
- print_device(device);
-
- return 0;
+ if (device == NULL)
+ log_warning_errno(errno, "udev_device_new_from_syspath: %m");
+ else
+ print_device(device);
}
-static int test_device_parents(struct udev *udev, const char *syspath) {
+static void test_device_parents(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
struct udev_device *device_parent;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL)
- return -1;
+ return;
- printf("looking at parents\n");
+ log_info("looking at parents");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
- printf("looking at parents again\n");
+ log_info("looking at parents again");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
-
- return 0;
}
-static int test_device_devnum(struct udev *udev) {
+static void test_device_devnum(struct udev *udev) {
dev_t devnum = makedev(1, 3);
- struct udev_device *device;
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ log_info("looking up device: %u:%u", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_devnum: %m");
+ else
+ print_device(device);
}
-static int test_device_subsys_name(struct udev *udev) {
- struct udev_device *device;
-
- printf("looking up device: 'block':'sda'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'subsystem':'pci'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'drivers':'scsi:sd'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
+static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: 'module':'printk'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
+ log_info("looking up device: '%s:%s'", subsys, dev);
+ device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
+ else
+ print_device(device);
}
static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
@@ -198,63 +170,45 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
if (device != NULL) {
- printf("device: '%s' (%s)\n",
- udev_device_get_syspath(device),
- udev_device_get_subsystem(device));
+ log_info("device: '%s' (%s)",
+ udev_device_get_syspath(device),
+ udev_device_get_subsystem(device));
udev_device_unref(device);
count++;
}
}
- printf("found %i devices\n\n", count);
+ log_info("found %i devices", count);
return count;
}
-static int test_monitor(struct udev *udev) {
- struct udev_monitor *udev_monitor = NULL;
- int fd_ep;
- int fd_udev = -1;
- struct epoll_event ep_udev, ep_stdin;
+static void test_monitor(struct udev *udev) {
+ _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor;
+ _cleanup_close_ int fd_ep;
+ int fd_udev;
+ struct epoll_event ep_udev = {
+ .events = EPOLLIN,
+ }, ep_stdin = {
+ .events = EPOLLIN,
+ .data.fd = STDIN_FILENO,
+ };
fd_ep = epoll_create1(EPOLL_CLOEXEC);
- if (fd_ep < 0) {
- printf("error creating epoll fd: %m\n");
- goto out;
- }
+ assert_se(fd_ep >= 0);
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (udev_monitor == NULL) {
- printf("no socket\n");
- goto out;
- }
+ assert_se(udev_monitor != NULL);
+
fd_udev = udev_monitor_get_fd(udev_monitor);
+ ep_udev.data.fd = fd_udev;
- if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
- printf("filter failed\n");
- goto out;
- }
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0);
- if (udev_monitor_enable_receiving(udev_monitor) < 0) {
- printf("bind failed\n");
- goto out;
- }
+ assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0);
- memzero(&ep_udev, sizeof(struct epoll_event));
- ep_udev.events = EPOLLIN;
- ep_udev.data.fd = fd_udev;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
-
- memzero(&ep_stdin, sizeof(struct epoll_event));
- ep_stdin.events = EPOLLIN;
- ep_stdin.data.fd = STDIN_FILENO;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0);
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0);
for (;;) {
int fdcount;
@@ -263,7 +217,7 @@ static int test_monitor(struct udev *udev) {
int i;
printf("waiting for events from udev, press ENTER to exit\n");
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
+ fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
printf("epoll fd count: %i\n", fdcount);
for (i = 0; i < fdcount; i++) {
@@ -277,36 +231,29 @@ static int test_monitor(struct udev *udev) {
udev_device_unref(device);
} else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
printf("exiting loop\n");
- goto out;
+ return;
}
}
}
-out:
- if (fd_ep >= 0)
- close(fd_ep);
- udev_monitor_unref(udev_monitor);
- return 0;
}
-static int test_queue(struct udev *udev) {
+static void test_queue(struct udev *udev) {
struct udev_queue *udev_queue;
+ bool empty;
udev_queue = udev_queue_new(udev);
- if (udev_queue == NULL)
- return -1;
-
- if (udev_queue_get_queue_is_empty(udev_queue))
- printf("queue is empty\n");
+ assert_se(udev_queue);
+ empty = udev_queue_get_queue_is_empty(udev_queue);
+ log_info("queue is %s", empty ? "empty" : "not empty");
udev_queue_unref(udev_queue);
- return 0;
}
static int test_enumerate(struct udev *udev, const char *subsystem) {
struct udev_enumerate *udev_enumerate;
int r;
- printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
+ log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -315,7 +262,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'net' + duplicated scan + null + zero\n");
+ log_info("enumerate 'net' + duplicated scan + null + zero");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -335,7 +282,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'block'\n");
+ log_info("enumerate 'block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -349,7 +296,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'not block'\n");
+ log_info("enumerate 'not block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -358,7 +305,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'pci, mem, vc'\n");
+ log_info("enumerate 'pci, mem, vc'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -369,7 +316,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'subsystem'\n");
+ log_info("enumerate 'subsystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -377,7 +324,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'property IF_FS_*=filesystem'\n");
+ log_info("enumerate 'property IF_FS_*=filesystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -395,32 +342,32 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
hwdb = udev_hwdb_new(udev);
udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
- printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
- printf("\n");
+ log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
hwdb = udev_hwdb_unref(hwdb);
assert_se(hwdb == NULL);
}
int main(int argc, char *argv[]) {
- struct udev *udev = NULL;
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ bool arg_monitor = false;
static const struct option options[] = {
- { "syspath", required_argument, NULL, 'p' },
+ { "syspath", required_argument, NULL, 'p' },
{ "subsystem", required_argument, NULL, 's' },
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'V' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "monitor", no_argument, NULL, 'm' },
{}
};
const char *syspath = "/devices/virtual/mem/null";
const char *subsystem = NULL;
- char path[1024];
int c;
udev = udev_new();
- printf("context: %p\n", udev);
+ log_info("context: %p", udev);
if (udev == NULL) {
- printf("no context\n");
+ log_info("no context");
return 1;
}
@@ -442,14 +389,18 @@ int main(int argc, char *argv[]) {
case 'h':
printf("--debug --syspath= --subsystem= --help\n");
- goto out;
+ return EXIT_SUCCESS;
case 'V':
printf("%s\n", VERSION);
- goto out;
+ return EXIT_SUCCESS;
+
+ case 'm':
+ arg_monitor = true;
+ break;
case '?':
- goto out;
+ return EXIT_FAILURE;
default:
assert_not_reached("Unhandled option code.");
@@ -457,14 +408,16 @@ int main(int argc, char *argv[]) {
/* add sys path if needed */
- if (!startswith(syspath, "/sys")) {
- snprintf(path, sizeof(path), "/sys/%s", syspath);
- syspath = path;
- }
+ if (!startswith(syspath, "/sys"))
+ syspath = strjoina("/sys/", syspath);
test_device(udev, syspath);
test_device_devnum(udev);
- test_device_subsys_name(udev);
+ test_device_subsys_name(udev, "block", "sda");
+ test_device_subsys_name(udev, "subsystem", "pci");
+ test_device_subsys_name(udev, "drivers", "scsi:sd");
+ test_device_subsys_name(udev, "module", "printk");
+
test_device_parents(udev, syspath);
test_enumerate(udev, subsystem);
@@ -473,8 +426,8 @@ int main(int argc, char *argv[]) {
test_hwdb(udev, "usb:v0D50p0011*");
- test_monitor(udev);
-out:
- udev_unref(udev);
- return 0;
+ if (arg_monitor)
+ test_monitor(udev);
+
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-list.c b/src/test/test-list.c
index f6da1a7053..0ccd745cc9 100644
--- a/src/test/test-list.c
+++ b/src/test/test-list.c
@@ -99,6 +99,73 @@ int main(int argc, const char *argv[]) {
assert_se(items[1].item_prev == &items[3]);
assert_se(items[3].item_prev == NULL);
+ LIST_REMOVE(item, head, &items[1]);
+ assert_se(LIST_JUST_US(item, &items[1]));
+
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[2].item_next == &items[0]);
+ assert_se(items[3].item_next == &items[2]);
+
+ assert_se(items[0].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_INSERT_BEFORE(item, head, &items[2], &items[1]);
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[2].item_next == &items[0]);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[0].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_REMOVE(item, head, &items[0]);
+ assert_se(LIST_JUST_US(item, &items[0]));
+
+ assert_se(items[2].item_next == NULL);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_INSERT_BEFORE(item, head, &items[3], &items[0]);
+ assert_se(items[2].item_next == NULL);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+ assert_se(items[0].item_next == &items[3]);
+
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == &items[0]);
+ assert_se(items[0].item_prev == NULL);
+ assert_se(head == &items[0]);
+
+ LIST_REMOVE(item, head, &items[0]);
+ assert_se(LIST_JUST_US(item, &items[0]));
+
+ assert_se(items[2].item_next == NULL);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_INSERT_BEFORE(item, head, NULL, &items[0]);
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[2].item_next == &items[0]);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[0].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
LIST_REMOVE(item, head, &items[0]);
assert_se(LIST_JUST_US(item, &items[0]));
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 9765075365..427c698d1d 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -19,8 +19,8 @@
#include "locale-util.h"
-#include "strv.h"
#include "macro.h"
+#include "strv.h"
static void test_get_locales(void) {
_cleanup_strv_free_ char **locales = NULL;
diff --git a/src/test/test-log.c b/src/test/test-log.c
index 9dcfa2f274..55a2f9d23b 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,9 +20,9 @@
#include <stddef.h>
#include <unistd.h>
+#include "formats-util.h"
#include "log.h"
#include "util.h"
-#include "formats-util.h"
int main(int argc, char* argv[]) {
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index c03bda4382..7b67337331 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,11 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
-#include "loopback-setup.h"
#include "log.h"
+#include "loopback-setup.h"
int main(int argc, char* argv[]) {
int r;
@@ -31,8 +29,9 @@ int main(int argc, char* argv[]) {
log_open();
log_parse_environment();
- if ((r = loopback_setup()) < 0)
- fprintf(stderr, "loopback: %s\n", strerror(-r));
+ r = loopback_setup();
+ if (r < 0)
+ log_error("loopback: %m");
- return 0;
+ return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 7d7e08dc5d..ff9f35cecd 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,9 +19,12 @@
#include <sys/socket.h>
+#include "alloc-util.h"
+#include "fd-util.h"
#include "namespace.h"
-#include "util.h"
#include "process-util.h"
+#include "string-util.h"
+#include "util.h"
static void test_tmpdir(const char *id, const char *A, const char *B) {
_cleanup_free_ char *a, *b;
@@ -68,8 +69,10 @@ static void test_netns(void) {
int r, n = 0;
siginfo_t si;
- if (geteuid() > 0)
- return;
+ if (geteuid() > 0) {
+ log_info("Skipping test: not root");
+ exit(EXIT_TEST_SKIP);
+ }
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0);
@@ -123,6 +126,9 @@ int main(int argc, char *argv[]) {
char boot_id[SD_ID128_STRING_MAX];
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
+ log_parse_environment();
+ log_open();
+
assert_se(sd_id128_get_boot(&bid) >= 0);
sd_id128_to_string(bid, boot_id);
diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c
index 2879d7450f..bc6dd0926c 100644
--- a/src/test/test-netlink-manual.c
+++ b/src/test/test-netlink-manual.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,15 +18,16 @@
***/
#include <arpa/inet.h>
-#include <net/if.h>
+#include <libkmod.h>
#include <linux/ip.h>
+#include <net/if.h>
#include <linux/if_tunnel.h>
-#include <libkmod.h>
-#include "util.h"
-#include "macro.h"
#include "sd-netlink.h"
+#include "macro.h"
+#include "util.h"
+
static int load_module(const char *mod_name) {
struct kmod_ctx *ctx;
struct kmod_list *list = NULL, *l;
@@ -69,10 +68,10 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
/* skip test if module cannot be loaded */
r = load_module("ipip");
- if(r < 0)
+ if (r < 0)
return EXIT_TEST_SKIP;
- if(getuid() != 0)
+ if (getuid() != 0)
return EXIT_TEST_SKIP;
/* IPIP tunnel */
@@ -100,7 +99,7 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
assert_se((m = sd_netlink_message_unref(m)) == NULL);
r = load_module("sit");
- if(r < 0)
+ if (r < 0)
return EXIT_TEST_SKIP;
/* sit */
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index 3050be9e9d..c4d4da6d05 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,19 +20,24 @@
#include <stdlib.h>
#include <unistd.h>
-#include "namespace.h"
#include "log.h"
+#include "namespace.h"
int main(int argc, char *argv[]) {
const char * const writable[] = {
"/home",
+ "-/home/lennart/projects/foobar", /* this should be masked automatically */
NULL
};
const char * const readonly[] = {
- "/",
- "/usr",
+ /* "/", */
+ /* "/usr", */
"/boot",
+ "/lib",
+ "/usr/lib",
+ "-/lib64",
+ "-/usr/lib64",
NULL
};
@@ -44,11 +47,12 @@ int main(int argc, char *argv[]) {
};
char *root_directory;
char *projects_directory;
-
int r;
char tmp_dir[] = "/tmp/systemd-private-XXXXXX",
var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX";
+ log_set_max_level(LOG_DEBUG);
+
assert_se(mkdtemp(tmp_dir));
assert_se(mkdtemp(var_tmp_dir));
@@ -70,7 +74,8 @@ int main(int argc, char *argv[]) {
(char **) inaccessible,
tmp_dir,
var_tmp_dir,
- NULL,
+ true,
+ true,
true,
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
diff --git a/src/test/test-nss.c b/src/test/test-nss.c
new file mode 100644
index 0000000000..c43bda5917
--- /dev/null
+++ b/src/test/test-nss.c
@@ -0,0 +1,454 @@
+/***
+ 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 <dlfcn.h>
+#include <stdlib.h>
+#include <net/if.h>
+
+#include "log.h"
+#include "nss-util.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "alloc-util.h"
+#include "in-addr-util.h"
+#include "hexdecoct.h"
+#include "af-list.h"
+#include "stdio-util.h"
+#include "strv.h"
+#include "errno-list.h"
+#include "hostname-util.h"
+#include "local-addresses.h"
+
+static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) {
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ return "NSS_STATUS_TRYAGAIN";
+ case NSS_STATUS_UNAVAIL:
+ return "NSS_STATUS_UNAVAIL";
+ case NSS_STATUS_NOTFOUND:
+ return "NSS_STATUS_NOTFOUND";
+ case NSS_STATUS_SUCCESS:
+ return "NSS_STATUS_SUCCESS";
+ case NSS_STATUS_RETURN:
+ return "NSS_STATUS_RETURN";
+ default:
+ snprintf(buf, buf_len, "%i", status);
+ return buf;
+ }
+};
+
+static const char* af_to_string(int family, char *buf, size_t buf_len) {
+ const char *name;
+
+ if (family == AF_UNSPEC)
+ return "*";
+
+ name = af_to_name(family);
+ if (name)
+ return name;
+
+ snprintf(buf, buf_len, "%i", family);
+ return buf;
+}
+
+static void* open_handle(const char* dir, const char* module, int flags) {
+ const char *path;
+ void *handle;
+
+ if (dir)
+ path = strjoina(dir, "/.libs/libnss_", module, ".so.2");
+ else
+ path = strjoina("libnss_", module, ".so.2");
+
+ handle = dlopen(path, flags);
+ assert_se(handle);
+ return handle;
+}
+
+static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
+ const struct gaih_addrtuple *it;
+ int n = 0;
+
+ for (it = tuples; it; it = it->next) {
+ _cleanup_free_ char *a = NULL;
+ union in_addr_union u;
+ int r;
+ char family_name[DECIMAL_STR_MAX(int)];
+ char ifname[IF_NAMESIZE];
+
+ memcpy(&u, it->addr, 16);
+ r = in_addr_to_string(it->family, &u, &a);
+ assert_se(r == 0 || r == -EAFNOSUPPORT);
+ if (r == -EAFNOSUPPORT)
+ assert_se((a = hexmem(it->addr, 16)));
+
+ if (it->scopeid == 0)
+ goto numerical_index;
+
+ if (if_indextoname(it->scopeid, ifname) == NULL) {
+ log_warning("if_indextoname(%d) failed: %m", it->scopeid);
+ numerical_index:
+ xsprintf(ifname, "%i", it->scopeid);
+ };
+
+ log_info(" \"%s\" %s %s %%%s",
+ it->name,
+ af_to_string(it->family, family_name, sizeof family_name),
+ a,
+ ifname);
+ n ++;
+ }
+ return n;
+}
+
+static void print_struct_hostent(struct hostent *host, const char *canon) {
+ char **s;
+
+ log_info(" \"%s\"", host->h_name);
+ STRV_FOREACH(s, host->h_aliases)
+ log_info(" alias \"%s\"", *s);
+ STRV_FOREACH(s, host->h_addr_list) {
+ union in_addr_union u;
+ _cleanup_free_ char *a = NULL;
+ char family_name[DECIMAL_STR_MAX(int)];
+ int r;
+
+ assert_se((unsigned) host->h_length == FAMILY_ADDRESS_SIZE(host->h_addrtype));
+ memcpy(&u, *s, host->h_length);
+ r = in_addr_to_string(host->h_addrtype, &u, &a);
+ assert_se(r == 0);
+ log_info(" %s %s",
+ af_to_string(host->h_addrtype, family_name, sizeof family_name),
+ a);
+ }
+ if (canon)
+ log_info(" canonical: \"%s\"", canon);
+}
+
+static void test_gethostbyname4_r(void *handle, const char *module, const char *name) {
+ const char *fname;
+ _nss_gethostbyname4_r_t f;
+ char buffer[2000];
+ struct gaih_addrtuple *pat = NULL;
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl,
+ and will access this variable through *ttlp,
+ so we need to set it to something.
+ I'm not sure if this is a bug in nss-dns
+ or not. */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ int n;
+
+ fname = strjoina("_nss_", module, "_gethostbyname4_r");
+ f = dlsym(handle, fname);
+ log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+ assert_se(f);
+
+ status = f(name, &pat, buffer, sizeof buffer, &errno1, &errno2, &ttl);
+ if (status == NSS_STATUS_SUCCESS) {
+ log_info("%s(\"%s\") → status=%s%-20spat=buffer+0x%tx errno=%d/%s h_errno=%d/%s ttl=%"PRIi32,
+ fname, name,
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ pat ? (char*) pat - buffer : 0,
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2),
+ ttl);
+ n = print_gaih_addrtuples(pat);
+ } else {
+ log_info("%s(\"%s\") → status=%s%-20spat=0x%p errno=%d/%s h_errno=%d/%s",
+ fname, name,
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ pat,
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2));
+ n = 0;
+ }
+
+ if (STR_IN_SET(module, "resolve", "mymachines") && status == NSS_STATUS_UNAVAIL)
+ return;
+
+ if (STR_IN_SET(module, "myhostname", "resolve") && streq(name, "localhost")) {
+ assert_se(status == NSS_STATUS_SUCCESS);
+ assert_se(n == 2);
+ }
+}
+
+
+static void test_gethostbyname3_r(void *handle, const char *module, const char *name, int af) {
+ const char *fname;
+ _nss_gethostbyname3_r_t f;
+ char buffer[2000];
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl,
+ and will access this variable through *ttlp,
+ so we need to set it to something.
+ I'm not sure if this is a bug in nss-dns
+ or not. */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ struct hostent host;
+ char *canon;
+ char family_name[DECIMAL_STR_MAX(int)];
+
+ fname = strjoina("_nss_", module, "_gethostbyname3_r");
+ f = dlsym(handle, fname);
+ log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+ assert_se(f);
+
+ status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl, &canon);
+ log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32,
+ fname, name, af_to_string(af, family_name, sizeof family_name),
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2),
+ ttl);
+ if (status == NSS_STATUS_SUCCESS)
+ print_struct_hostent(&host, canon);
+}
+
+static void test_gethostbyname2_r(void *handle, const char *module, const char *name, int af) {
+ const char *fname;
+ _nss_gethostbyname2_r_t f;
+ char buffer[2000];
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ struct hostent host;
+ char family_name[DECIMAL_STR_MAX(int)];
+
+ fname = strjoina("_nss_", module, "_gethostbyname2_r");
+ f = dlsym(handle, fname);
+ log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+ assert_se(f);
+
+ status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2);
+ log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s",
+ fname, name, af_to_string(af, family_name, sizeof family_name),
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2));
+ if (status == NSS_STATUS_SUCCESS)
+ print_struct_hostent(&host, NULL);
+}
+
+static void test_gethostbyname_r(void *handle, const char *module, const char *name) {
+ const char *fname;
+ _nss_gethostbyname_r_t f;
+ char buffer[2000];
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ struct hostent host;
+
+ fname = strjoina("_nss_", module, "_gethostbyname_r");
+ f = dlsym(handle, fname);
+ log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+ assert_se(f);
+
+ status = f(name, &host, buffer, sizeof buffer, &errno1, &errno2);
+ log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s",
+ fname, name,
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2));
+ if (status == NSS_STATUS_SUCCESS)
+ print_struct_hostent(&host, NULL);
+}
+
+static void test_gethostbyaddr2_r(void *handle,
+ const char *module,
+ const void* addr, socklen_t len,
+ int af) {
+
+ const char *fname;
+ _nss_gethostbyaddr2_r_t f;
+ char buffer[2000];
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ struct hostent host;
+ int32_t ttl = INT32_MAX;
+ _cleanup_free_ char *addr_pretty = NULL;
+
+ fname = strjoina("_nss_", module, "_gethostbyaddr2_r");
+ f = dlsym(handle, fname);
+
+ log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno,
+ "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f);
+ if (!f)
+ return;
+
+ assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0);
+
+ status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl);
+ log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32,
+ fname, addr_pretty,
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2),
+ ttl);
+ if (status == NSS_STATUS_SUCCESS)
+ print_struct_hostent(&host, NULL);
+}
+
+static void test_gethostbyaddr_r(void *handle,
+ const char *module,
+ const void* addr, socklen_t len,
+ int af) {
+
+ const char *fname;
+ _nss_gethostbyaddr_r_t f;
+ char buffer[2000];
+ int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
+ enum nss_status status;
+ char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+ struct hostent host;
+ _cleanup_free_ char *addr_pretty = NULL;
+
+ fname = strjoina("_nss_", module, "_gethostbyaddr_r");
+ f = dlsym(handle, fname);
+
+ log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno,
+ "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f);
+ if (!f)
+ return;
+
+ assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0);
+
+ status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2);
+ log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s",
+ fname, addr_pretty,
+ nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+ errno1, errno_to_name(errno1) ?: "---",
+ errno2, hstrerror(errno2));
+ if (status == NSS_STATUS_SUCCESS)
+ print_struct_hostent(&host, NULL);
+}
+
+static void test_byname(void *handle, const char *module, const char *name) {
+ test_gethostbyname4_r(handle, module, name);
+ puts("");
+
+ test_gethostbyname3_r(handle, module, name, AF_INET);
+ puts("");
+ test_gethostbyname3_r(handle, module, name, AF_INET6);
+ puts("");
+ test_gethostbyname3_r(handle, module, name, AF_UNSPEC);
+ puts("");
+ test_gethostbyname3_r(handle, module, name, AF_LOCAL);
+ puts("");
+
+ test_gethostbyname2_r(handle, module, name, AF_INET);
+ puts("");
+ test_gethostbyname2_r(handle, module, name, AF_INET6);
+ puts("");
+ test_gethostbyname2_r(handle, module, name, AF_UNSPEC);
+ puts("");
+ test_gethostbyname2_r(handle, module, name, AF_LOCAL);
+ puts("");
+
+ test_gethostbyname_r(handle, module, name);
+ puts("");
+}
+
+static void test_byaddr(void *handle,
+ const char *module,
+ const void* addr, socklen_t len,
+ int af) {
+ test_gethostbyaddr2_r(handle, module, addr, len, af);
+ puts("");
+
+ test_gethostbyaddr_r(handle, module, addr, len, af);
+ puts("");
+}
+
+#ifdef HAVE_MYHOSTNAME
+# define MODULE1 "myhostname\0"
+#else
+# define MODULE1
+#endif
+#ifdef HAVE_RESOLVED
+# define MODULE2 "resolve\0"
+#else
+# define MODULE2
+#endif
+#ifdef HAVE_MACHINED
+# define MODULE3 "mymachines\0"
+#else
+# define MODULE3
+#endif
+#define MODULE4 "dns\0"
+
+int main(int argc, char **argv) {
+ _cleanup_free_ char *dir = NULL, *hostname = NULL;
+ const char *module;
+
+ const uint32_t local_address_ipv4 = htobe32(0x7F000001);
+ const uint32_t local_address_ipv4_2 = htobe32(0x7F000002);
+ _cleanup_free_ struct local_address *addresses = NULL;
+ int n_addresses;
+
+ log_set_max_level(LOG_INFO);
+ log_parse_environment();
+
+ dir = dirname_malloc(argv[0]);
+ assert_se(dir);
+
+ hostname = gethostname_malloc();
+ assert_se(hostname);
+
+ n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
+ if (n_addresses < 0) {
+ log_info_errno(n_addresses, "Failed to query local addresses: %m");
+ n_addresses = 0;
+ }
+
+ NULSTR_FOREACH(module, MODULE1 MODULE2 MODULE3 MODULE4) {
+ void *handle;
+ const char *name;
+ int i;
+
+ log_info("======== %s ========", module);
+
+ handle = open_handle(streq(module, "dns") ? NULL : dir,
+ module,
+ RTLD_LAZY|RTLD_NODELETE);
+ NULSTR_FOREACH(name, "localhost\0" "gateway\0" "foo_no_such_host\0")
+ test_byname(handle, module, name);
+
+ test_byname(handle, module, hostname);
+
+ test_byaddr(handle, module, &local_address_ipv4, sizeof local_address_ipv4, AF_INET);
+ test_byaddr(handle, module, &local_address_ipv4_2, sizeof local_address_ipv4_2, AF_INET);
+ test_byaddr(handle, module, &in6addr_loopback, sizeof in6addr_loopback, AF_INET6);
+
+ for (i = 0; i < n_addresses; i++)
+ test_byaddr(handle, module,
+ &addresses[i].address,
+ FAMILY_ADDRESS_SIZE(addresses[i].family),
+ addresses[i].family);
+
+ dlclose(handle);
+
+ log_info(" ");
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
new file mode 100644
index 0000000000..d08014100b
--- /dev/null
+++ b/src/test/test-parse-util.c
@@ -0,0 +1,547 @@
+/***
+ 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 <locale.h>
+#include <math.h>
+
+#include "log.h"
+#include "parse-util.h"
+
+static void test_parse_boolean(void) {
+ assert_se(parse_boolean("1") == 1);
+ assert_se(parse_boolean("y") == 1);
+ assert_se(parse_boolean("Y") == 1);
+ assert_se(parse_boolean("yes") == 1);
+ assert_se(parse_boolean("YES") == 1);
+ assert_se(parse_boolean("true") == 1);
+ assert_se(parse_boolean("TRUE") == 1);
+ assert_se(parse_boolean("on") == 1);
+ assert_se(parse_boolean("ON") == 1);
+
+ assert_se(parse_boolean("0") == 0);
+ assert_se(parse_boolean("n") == 0);
+ assert_se(parse_boolean("N") == 0);
+ assert_se(parse_boolean("no") == 0);
+ assert_se(parse_boolean("NO") == 0);
+ assert_se(parse_boolean("false") == 0);
+ assert_se(parse_boolean("FALSE") == 0);
+ assert_se(parse_boolean("off") == 0);
+ assert_se(parse_boolean("OFF") == 0);
+
+ assert_se(parse_boolean("garbage") < 0);
+ assert_se(parse_boolean("") < 0);
+ assert_se(parse_boolean("full") < 0);
+}
+
+static void test_parse_pid(void) {
+ int r;
+ pid_t pid;
+
+ r = parse_pid("100", &pid);
+ assert_se(r == 0);
+ assert_se(pid == 100);
+
+ r = parse_pid("0x7FFFFFFF", &pid);
+ assert_se(r == 0);
+ assert_se(pid == 2147483647);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("0", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("-100", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ r = parse_pid("junk", &pid);
+ assert_se(r == -EINVAL);
+}
+
+static void test_parse_mode(void) {
+ mode_t m;
+
+ assert_se(parse_mode("-1", &m) < 0);
+ assert_se(parse_mode("", &m) < 0);
+ assert_se(parse_mode("888", &m) < 0);
+ assert_se(parse_mode("77777", &m) < 0);
+
+ assert_se(parse_mode("544", &m) >= 0 && m == 0544);
+ assert_se(parse_mode("777", &m) >= 0 && m == 0777);
+ assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
+ assert_se(parse_mode("0", &m) >= 0 && m == 0);
+}
+
+static void test_parse_size(void) {
+ uint64_t bytes;
+
+ assert_se(parse_size("111", 1024, &bytes) == 0);
+ assert_se(bytes == 111);
+
+ assert_se(parse_size("111.4", 1024, &bytes) == 0);
+ assert_se(bytes == 111);
+
+ assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
+ assert_se(bytes == 112);
+
+ assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
+ assert_se(bytes == 112);
+
+ assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024 + 512);
+
+ assert_se(parse_size("3. K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024);
+
+ assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024);
+
+ assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
+ assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
+
+ assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
+ assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
+
+ assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
+ assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
+
+ assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
+ assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
+
+ assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
+ assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
+
+ assert_se(parse_size("12P", 1024, &bytes) == 0);
+ assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
+ assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
+ assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
+ assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
+
+ assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
+
+ assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
+}
+
+static void test_parse_range(void) {
+ unsigned lower, upper;
+
+ /* Successful cases */
+ assert_se(parse_range("111", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 111);
+
+ assert_se(parse_range("111-123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("123-111", &lower, &upper) == 0);
+ assert_se(lower == 123);
+ assert_se(upper == 111);
+
+ assert_se(parse_range("123-123", &lower, &upper) == 0);
+ assert_se(lower == 123);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("0", &lower, &upper) == 0);
+ assert_se(lower == 0);
+ assert_se(upper == 0);
+
+ assert_se(parse_range("0-15", &lower, &upper) == 0);
+ assert_se(lower == 0);
+ assert_se(upper == 15);
+
+ assert_se(parse_range("15-0", &lower, &upper) == 0);
+ assert_se(lower == 15);
+ assert_se(upper == 0);
+
+ assert_se(parse_range("128-65535", &lower, &upper) == 0);
+ assert_se(lower == 128);
+ assert_se(upper == 65535);
+
+ assert_se(parse_range("1024-4294967295", &lower, &upper) == 0);
+ assert_se(lower == 1024);
+ assert_se(upper == 4294967295);
+
+ /* Leading whitespace is acceptable */
+ assert_se(parse_range(" 111", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 111);
+
+ assert_se(parse_range(" 111-123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("111- 123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("\t111-\t123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ /* Error cases, make sure they fail as expected */
+ lower = upper = 9999;
+ assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Empty string */
+ lower = upper = 9999;
+ assert_se(parse_range("", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */
+ assert_se(parse_range("111--123", &lower, &upper) == -ERANGE);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Error on trailing dash */
+ assert_se(parse_range("111-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111--", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111- ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Whitespace is not a separator */
+ assert_se(parse_range("111 123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Trailing whitespace is invalid (from safe_atou) */
+ assert_se(parse_range("111 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Out of the "unsigned" range, this is 1<<64 */
+ assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+}
+
+static void test_safe_atolli(void) {
+ int r;
+ long long l;
+
+ r = safe_atolli("12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atolli(" 12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atolli("-12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atolli(" -12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atolli("12345678901234567890", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atolli("-12345678901234567890", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atolli("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atou16(void) {
+ int r;
+ uint16_t l;
+
+ r = safe_atou16("12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atou16(" 12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atou16("123456", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atou16("-1", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atou16(" -1", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atou16("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atoi16(void) {
+ int r;
+ int16_t l;
+
+ r = safe_atoi16("-12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atoi16(" -12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atoi16("32767", &l);
+ assert_se(r == 0);
+ assert_se(l == 32767);
+
+ r = safe_atoi16(" 32767", &l);
+ assert_se(r == 0);
+ assert_se(l == 32767);
+
+ r = safe_atoi16("36536", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoi16("-32769", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoi16("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atod(void) {
+ int r;
+ double d;
+ char *e;
+
+ r = safe_atod("junk", &d);
+ assert_se(r == -EINVAL);
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ strtod("0,5", &e);
+ assert_se(*e == ',');
+
+ /* Check if this really is locale independent */
+ if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
+ }
+
+ /* And check again, reset */
+ assert_se(setlocale(LC_NUMERIC, "C"));
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ strtod("0,5", &e);
+ assert_se(*e == ',');
+}
+
+static void test_parse_percent(void) {
+ assert_se(parse_percent("") == -EINVAL);
+ assert_se(parse_percent("foo") == -EINVAL);
+ assert_se(parse_percent("0") == -EINVAL);
+ assert_se(parse_percent("50") == -EINVAL);
+ assert_se(parse_percent("100") == -EINVAL);
+ assert_se(parse_percent("-1") == -EINVAL);
+ assert_se(parse_percent("0%") == 0);
+ assert_se(parse_percent("55%") == 55);
+ assert_se(parse_percent("100%") == 100);
+ assert_se(parse_percent("-7%") == -ERANGE);
+ assert_se(parse_percent("107%") == -ERANGE);
+ assert_se(parse_percent("%") == -EINVAL);
+ assert_se(parse_percent("%%") == -EINVAL);
+ assert_se(parse_percent("%1") == -EINVAL);
+ assert_se(parse_percent("1%%") == -EINVAL);
+}
+
+static void test_parse_percent_unbounded(void) {
+ assert_se(parse_percent_unbounded("101%") == 101);
+ assert_se(parse_percent_unbounded("400%") == 400);
+}
+
+static void test_parse_nice(void) {
+ int n;
+
+ assert_se(parse_nice("0", &n) >= 0 && n == 0);
+ assert_se(parse_nice("+0", &n) >= 0 && n == 0);
+ assert_se(parse_nice("-1", &n) >= 0 && n == -1);
+ assert_se(parse_nice("-2", &n) >= 0 && n == -2);
+ assert_se(parse_nice("1", &n) >= 0 && n == 1);
+ assert_se(parse_nice("2", &n) >= 0 && n == 2);
+ assert_se(parse_nice("+1", &n) >= 0 && n == 1);
+ assert_se(parse_nice("+2", &n) >= 0 && n == 2);
+ assert_se(parse_nice("-20", &n) >= 0 && n == -20);
+ assert_se(parse_nice("19", &n) >= 0 && n == 19);
+ assert_se(parse_nice("+19", &n) >= 0 && n == 19);
+
+
+ assert_se(parse_nice("", &n) == -EINVAL);
+ assert_se(parse_nice("-", &n) == -EINVAL);
+ assert_se(parse_nice("+", &n) == -EINVAL);
+ assert_se(parse_nice("xx", &n) == -EINVAL);
+ assert_se(parse_nice("-50", &n) == -ERANGE);
+ assert_se(parse_nice("50", &n) == -ERANGE);
+ assert_se(parse_nice("+50", &n) == -ERANGE);
+ assert_se(parse_nice("-21", &n) == -ERANGE);
+ assert_se(parse_nice("20", &n) == -ERANGE);
+ assert_se(parse_nice("+20", &n) == -ERANGE);
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_boolean();
+ test_parse_pid();
+ test_parse_mode();
+ test_parse_size();
+ test_parse_range();
+ test_safe_atolli();
+ test_safe_atou16();
+ test_safe_atoi16();
+ test_safe_atod();
+ test_parse_percent();
+ test_parse_percent_unbounded();
+ test_parse_nice();
+
+ return 0;
+}
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
index aa4bac6cdd..096326d176 100644
--- a/src/test/test-path-lookup.c
+++ b/src/test/test-path-lookup.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,40 +17,47 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdlib.h>
#include <sys/stat.h>
-#include "path-lookup.h"
#include "log.h"
-#include "strv.h"
+#include "path-lookup.h"
#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
-static void test_paths(ManagerRunningAs running_as, bool personal) {
+static void test_paths(UnitFileScope scope) {
char template[] = "/tmp/test-path-lookup.XXXXXXX";
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
- char *exists, *not;
+ _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {};
+ _cleanup_lookup_paths_free_ LookupPaths lp_with_env = {};
+ char *systemd_unit_path;
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(unsetenv("SYSTEMD_UNIT_PATH") == 0);
+ assert_se(lookup_paths_init(&lp_without_env, scope, 0, NULL) >= 0);
+ assert_se(!strv_isempty(lp_without_env.search_path));
+ assert_se(lookup_paths_reduce(&lp_without_env) >= 0);
- assert_se(!strv_isempty(lp.unit_path));
- assert_se(strv_contains(lp.unit_path, exists));
- assert_se(strv_contains(lp.unit_path, not));
+ systemd_unit_path = strjoina(template, "/systemd-unit-path");
+ assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0);
+ assert_se(lookup_paths_init(&lp_with_env, scope, 0, NULL) == 0);
+ assert_se(strv_length(lp_with_env.search_path) == 1);
+ assert_se(streq(lp_with_env.search_path[0], systemd_unit_path));
+ assert_se(lookup_paths_reduce(&lp_with_env) >= 0);
+ assert_se(strv_length(lp_with_env.search_path) == 0);
assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
-static void print_generator_paths(ManagerRunningAs running_as) {
+static void print_generator_binary_paths(UnitFileScope scope) {
_cleanup_strv_free_ char **paths;
char **dir;
- log_info("Generators dirs (%s):", running_as == MANAGER_SYSTEM ? "system" : "user");
+ log_info("Generators dirs (%s):", scope == UNIT_FILE_SYSTEM ? "system" : "user");
- paths = generator_paths(running_as);
+ paths = generator_binary_paths(scope);
STRV_FOREACH(dir, paths)
log_info(" %s", *dir);
}
@@ -62,13 +67,12 @@ int main(int argc, char **argv) {
log_parse_environment();
log_open();
- test_paths(MANAGER_SYSTEM, false);
- test_paths(MANAGER_SYSTEM, true);
- test_paths(MANAGER_USER, false);
- test_paths(MANAGER_USER, true);
+ test_paths(UNIT_FILE_SYSTEM);
+ test_paths(UNIT_FILE_USER);
+ test_paths(UNIT_FILE_GLOBAL);
- print_generator_paths(MANAGER_SYSTEM);
- print_generator_paths(MANAGER_USER);
+ print_generator_binary_paths(UNIT_FILE_SYSTEM);
+ print_generator_binary_paths(UNIT_FILE_USER);
return EXIT_SUCCESS;
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index fce4e81a09..0b10d8e25e 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,14 +18,18 @@
***/
#include <stdio.h>
-#include <unistd.h>
#include <sys/mount.h>
+#include <unistd.h>
-#include "path-util.h"
-#include "util.h"
+#include "alloc-util.h"
+#include "fd-util.h"
#include "macro.h"
-#include "strv.h"
+#include "mount-util.h"
+#include "path-util.h"
#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
#define test_path_compare(a, b, result) { \
assert_se(path_compare(a, b) == result); \
@@ -75,20 +77,6 @@ static void test_path(void) {
assert_se(streq(basename("/aa///file..."), "file..."));
assert_se(streq(basename("file.../"), ""));
-#define test_parent(x, y) { \
- _cleanup_free_ char *z = NULL; \
- int r = path_get_parent(x, &z); \
- printf("expected: %s\n", y ? y : "error"); \
- printf("actual: %s\n", r<0 ? "error" : z); \
- assert_se((y==NULL) ^ (r==0)); \
- assert_se(y==NULL || path_equal(z, y)); \
- }
-
- test_parent("./aa/bb/../file.da.", "./aa/bb/..");
- test_parent("/aa///.file", "/aa///");
- test_parent("/aa///file...", "/aa///");
- test_parent("file.../", NULL);
-
fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
assert_se(fd >= 0);
assert_se(fd_is_mount_point(fd, "/", 0) > 0);
@@ -102,34 +90,43 @@ static void test_path(void) {
assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
assert_se(path_equal(path_kill_slashes(p3), "/./"));
}
+
+ assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
+ assert_se(PATH_IN_SET("/bin", "/bin"));
+ assert_se(PATH_IN_SET("/bin", "/foo/bar", "/bin"));
+ assert_se(PATH_IN_SET("/", "/", "/", "/foo/bar"));
+ assert_se(!PATH_IN_SET("/", "/abc", "/def"));
+
+ assert_se(path_equal_ptr(NULL, NULL));
+ assert_se(path_equal_ptr("/a", "/a"));
+ assert_se(!path_equal_ptr("/a", "/b"));
+ assert_se(!path_equal_ptr("/a", NULL));
+ assert_se(!path_equal_ptr(NULL, "/a"));
}
-static void test_find_binary(const char *self, bool local) {
+static void test_find_binary(const char *self) {
char *p;
- assert_se(find_binary("/bin/sh", local, &p) == 0);
+ assert_se(find_binary("/bin/sh", &p) == 0);
puts(p);
- assert_se(streq(p, "/bin/sh"));
+ assert_se(path_equal(p, "/bin/sh"));
free(p);
- assert_se(find_binary(self, local, &p) == 0);
+ assert_se(find_binary(self, &p) == 0);
puts(p);
- assert_se(endswith(p, "/test-path-util"));
+ /* libtool might prefix the binary name with "lt-" */
+ assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util"));
assert_se(path_is_absolute(p));
free(p);
- assert_se(find_binary("sh", local, &p) == 0);
+ assert_se(find_binary("sh", &p) == 0);
puts(p);
assert_se(endswith(p, "/sh"));
assert_se(path_is_absolute(p));
free(p);
- assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
-
- assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
- (local ? -ENOENT : 0));
- if (!local)
- free(p);
+ assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT);
+ assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT);
}
static void test_prefixes(void) {
@@ -210,9 +207,10 @@ static void test_fsck_exists(void) {
unsetenv("PATH");
/* fsck.minix is provided by util-linux and will probably exist. */
- assert_se(fsck_exists("minix") == 0);
+ assert_se(fsck_exists("minix") == 1);
- assert_se(fsck_exists("AbCdE") == -ENOENT);
+ assert_se(fsck_exists("AbCdE") == 0);
+ assert_se(fsck_exists("/../bin/") == 0);
}
static void test_make_relative(void) {
@@ -448,10 +446,91 @@ static void test_path_is_mount_point(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
+static void test_file_in_same_dir(void) {
+ char *t;
+
+ t = file_in_same_dir("/", "a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("/", "/a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("", "a");
+ assert_se(streq(t, "a"));
+ free(t);
+
+ t = file_in_same_dir("a/", "a");
+ assert_se(streq(t, "a/a"));
+ free(t);
+
+ t = file_in_same_dir("bar/foo", "bar");
+ assert_se(streq(t, "bar/bar"));
+ free(t);
+}
+
+static void test_filename_is_valid(void) {
+ char foo[FILENAME_MAX+2];
+ int i;
+
+ 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_valid(foo));
+
+ assert_se(filename_is_valid("foo_bar-333"));
+ assert_se(filename_is_valid("o.o"));
+}
+
+static void test_hidden_or_backup_file(void) {
+ assert_se(hidden_or_backup_file(".hidden"));
+ assert_se(hidden_or_backup_file("..hidden"));
+ assert_se(!hidden_or_backup_file("hidden."));
+
+ assert_se(hidden_or_backup_file("backup~"));
+ assert_se(hidden_or_backup_file(".backup~"));
+
+ assert_se(hidden_or_backup_file("lost+found"));
+ assert_se(hidden_or_backup_file("aquota.user"));
+ assert_se(hidden_or_backup_file("aquota.group"));
+
+ assert_se(hidden_or_backup_file("test.rpmnew"));
+ assert_se(hidden_or_backup_file("test.dpkg-old"));
+ assert_se(hidden_or_backup_file("test.dpkg-remove"));
+ assert_se(hidden_or_backup_file("test.swp"));
+
+ assert_se(!hidden_or_backup_file("test.rpmnew."));
+ assert_se(!hidden_or_backup_file("test.dpkg-old.foo"));
+}
+
+static void test_systemd_installation_has_version(const char *path) {
+ int r;
+ const unsigned versions[] = {0, 231, atoi(PACKAGE_VERSION), 999};
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(versions); i++) {
+ r = systemd_installation_has_version(path, versions[i]);
+ assert_se(r >= 0);
+ log_info("%s has systemd >= %u: %s",
+ path ?: "Current installation", versions[i], yes_no(r));
+ }
+}
+
int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
test_path();
- test_find_binary(argv[0], true);
- test_find_binary(argv[0], false);
+ test_find_binary(argv[0]);
test_prefixes();
test_path_join();
test_fsck_exists();
@@ -460,6 +539,11 @@ int main(int argc, char **argv) {
test_path_startswith();
test_prefix_root();
test_path_is_mount_point();
+ test_file_in_same_dir();
+ test_filename_is_valid();
+ test_hidden_or_backup_file();
+
+ test_systemd_installation_has_version(argv[1]); /* NULL is OK */
return 0;
}
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 5d190378f1..4d3f0e9948 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -17,16 +17,22 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
-#include "unit.h"
-#include "manager.h"
-#include "util.h"
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
#include "macro.h"
-#include "strv.h"
+#include "manager.h"
#include "mkdir.h"
#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "test-helper.h"
+#include "tests.h"
+#include "unit.h"
+#include "util.h"
typedef void (*test_function_t)(Manager *m);
@@ -39,9 +45,9 @@ static int setup_test(Manager **m) {
assert_se(m);
- r = manager_new(MANAGER_USER, true, &tmp);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ r = manager_new(UNIT_FILE_USER, true, &tmp);
+ if (MANAGER_SKIP_TEST(r)) {
+ log_notice_errno(r, "Skipping test: manager_new: %m");
return -EXIT_TEST_SKIP;
}
assert_se(r >= 0);
@@ -88,7 +94,7 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
ts = now(CLOCK_MONOTONIC);
/* We process events until the service related to the path has been successfully started */
- while(service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
+ while (service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
usec_t n;
int r;
@@ -238,7 +244,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
}
int main(int argc, char *argv[]) {
- test_function_t tests[] = {
+ static const test_function_t tests[] = {
test_path_exists,
test_path_existsglob,
test_path_changed,
@@ -248,13 +254,16 @@ int main(int argc, char *argv[]) {
test_path_makedirectory_directorymode,
NULL,
};
- test_function_t *test = NULL;
+
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ const test_function_t *test = NULL;
Manager *m = NULL;
log_parse_environment();
log_open();
- assert_se(set_unit_path(TEST_DIR) >= 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-prioq.c b/src/test/test-prioq.c
index dfedc9b8dc..d81880a655 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,10 +19,11 @@
#include <stdlib.h>
-#include "util.h"
-#include "set.h"
+#include "alloc-util.h"
#include "prioq.h"
+#include "set.h"
#include "siphash24.h"
+#include "util.h"
#define SET_SIZE 1024*4
@@ -89,13 +88,10 @@ static int test_compare(const void *a, const void *b) {
return 0;
}
-static unsigned long test_hash(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
+static void test_hash(const void *a, struct siphash *state) {
const struct test *x = a;
- uint64_t u;
-
- siphash24((uint8_t*) &u, &x->value, sizeof(x->value), hash_key);
- return (unsigned long) u;
+ siphash24_compress(&x->value, sizeof(x->value), state);
}
static const struct hash_ops test_hash_ops = {
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
new file mode 100644
index 0000000000..80ad5ed98b
--- /dev/null
+++ b/src/test/test-proc-cmdline.c
@@ -0,0 +1,63 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "alloc-util.h"
+#include "log.h"
+#include "macro.h"
+#include "proc-cmdline.h"
+#include "special.h"
+#include "string-util.h"
+#include "util.h"
+
+static int parse_item(const char *key, const char *value) {
+ assert_se(key);
+
+ log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
+ return 0;
+}
+
+static void test_parse_proc_cmdline(void) {
+ assert_se(parse_proc_cmdline(parse_item) >= 0);
+}
+
+static void test_runlevel_to_target(void) {
+ in_initrd_force(false);
+ assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+ assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
+ assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL));
+
+ in_initrd_force(true);
+ assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+ assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("3"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET));
+}
+
+int main(void) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_proc_cmdline();
+ test_runlevel_to_target();
+
+ return 0;
+}
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index e4e2efecd5..9ada46b1e9 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -18,78 +18,88 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/personality.h>
+#include <sys/prctl.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
-#include "process-util.h"
+#include "alloc-util.h"
+#include "architecture.h"
+#include "fd-util.h"
#include "log.h"
-#include "util.h"
#include "macro.h"
-#include "virt.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "terminal-util.h"
+#include "test-helper.h"
+#include "util.h"
+#include "virt.h"
-static void test_get_process_comm(void) {
+static void test_get_process_comm(pid_t pid) {
struct stat st;
- _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL;
+ _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
_cleanup_free_ char *env = NULL;
+ char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
pid_t e;
uid_t u;
gid_t g;
dev_t h;
int r;
- pid_t me;
-
- if (stat("/proc/1/comm", &st) == 0) {
- assert_se(get_process_comm(1, &a) >= 0);
- log_info("pid1 comm: '%s'", a);
- } else
- log_warning("/proc/1/comm does not exist.");
-
- assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
- log_info("pid1 cmdline: '%s'", c);
- assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
- log_info("pid1 cmdline truncated: '%s'", d);
+ xsprintf(path, "/proc/"PID_FMT"/comm", pid);
- assert_se(get_parent_of_pid(1, &e) >= 0);
- log_info("pid1 ppid: "PID_FMT, e);
- assert_se(e == 0);
+ if (stat(path, &st) == 0) {
+ assert_se(get_process_comm(pid, &a) >= 0);
+ log_info("PID"PID_FMT" comm: '%s'", pid, a);
+ } else
+ log_warning("%s not exist.", path);
- assert_se(is_kernel_thread(1) == 0);
+ assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
+ log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
- r = get_process_exe(1, &f);
- assert_se(r >= 0 || r == -EACCES);
- log_info("pid1 exe: '%s'", strna(f));
+ assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
+ log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
- assert_se(get_process_uid(1, &u) == 0);
- log_info("pid1 uid: "UID_FMT, u);
- assert_se(u == 0);
+ free(d);
+ assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
+ log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
- assert_se(get_process_gid(1, &g) == 0);
- log_info("pid1 gid: "GID_FMT, g);
- assert_se(g == 0);
+ assert_se(get_process_ppid(pid, &e) >= 0);
+ log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
+ assert_se(pid == 1 ? e == 0 : e > 0);
- me = getpid();
+ assert_se(is_kernel_thread(pid) == 0 || pid != 1);
- r = get_process_cwd(me, &cwd);
+ r = get_process_exe(pid, &f);
assert_se(r >= 0 || r == -EACCES);
- log_info("pid1 cwd: '%s'", cwd);
+ log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
- r = get_process_root(me, &root);
- assert_se(r >= 0 || r == -EACCES);
- log_info("pid1 root: '%s'", root);
+ assert_se(get_process_uid(pid, &u) == 0);
+ log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
+ assert_se(u == 0 || pid != 1);
- r = get_process_environ(me, &env);
+ assert_se(get_process_gid(pid, &g) == 0);
+ log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
+ assert_se(g == 0 || pid != 1);
+
+ r = get_process_environ(pid, &env);
assert_se(r >= 0 || r == -EACCES);
- log_info("self strlen(environ): '%zu'", strlen(env));
+ log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
- if (!detect_container(NULL))
- assert_se(get_ctty_devnr(1, &h) == -ENXIO);
+ if (!detect_container())
+ assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
- getenv_for_pid(1, "PATH", &i);
- log_info("pid1 $PATH: '%s'", strna(i));
+ getenv_for_pid(pid, "PATH", &i);
+ log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
}
static void test_pid_is_unwaited(void) {
@@ -126,13 +136,236 @@ static void test_pid_is_alive(void) {
assert_se(!pid_is_alive(-1));
}
+static void test_personality(void) {
+
+ assert_se(personality_to_string(PER_LINUX));
+ assert_se(!personality_to_string(PERSONALITY_INVALID));
+
+ assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
+
+ assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
+ assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
+
+#ifdef __x86_64__
+ assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
+ assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
+
+ assert_se(personality_from_string("x86-64") == PER_LINUX);
+ assert_se(personality_from_string("x86") == PER_LINUX32);
+ assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
+ assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
+
+ assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
+#endif
+}
+
+static void test_get_process_cmdline_harder(void) {
+ char path[] = "/tmp/test-cmdlineXXXXXX";
+ _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *line = NULL;
+ pid_t pid;
+
+ if (geteuid() != 0)
+ return;
+
+#ifdef HAVE_VALGRIND_VALGRIND_H
+ /* valgrind patches open(/proc//cmdline)
+ * so, test_get_process_cmdline_harder fails always
+ * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
+ if (RUNNING_ON_VALGRIND)
+ return;
+#endif
+
+ pid = fork();
+ if (pid > 0) {
+ siginfo_t si;
+
+ (void) wait_for_terminate(pid, &si);
+
+ assert_se(si.si_code == CLD_EXITED);
+ assert_se(si.si_status == 0);
+
+ return;
+ }
+
+ assert_se(pid == 0);
+ assert_se(unshare(CLONE_NEWNS) >= 0);
+
+ fd = mkostemp(path, O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) >= 0);
+ assert_se(unlink(path) >= 0);
+
+ assert_se(prctl(PR_SET_NAME, "testa") >= 0);
+
+ assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+ assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(streq(line, "[testa]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+ assert_se(streq(line, ""));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+ assert_se(streq(line, "["));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+ assert_se(streq(line, "[."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+ assert_se(streq(line, "[.."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+ assert_se(streq(line, "[..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+ assert_se(streq(line, "[...]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+ assert_se(streq(line, "[t...]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+ assert_se(streq(line, "[testa]"));
+ line = mfree(line);
+
+ assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
+
+ assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+ assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(streq(line, "[testa]"));
+ line = mfree(line);
+
+ assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
+
+ assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+ assert_se(streq(line, "foo bar"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(streq(line, "foo bar"));
+ line = mfree(line);
+
+ assert_se(write(fd, "quux", 4) == 4);
+ assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+ assert_se(streq(line, ""));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+ assert_se(streq(line, "."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+ assert_se(streq(line, ".."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+ assert_se(streq(line, "..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+ assert_se(streq(line, "f..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+ assert_se(streq(line, "fo..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+ assert_se(streq(line, "foo..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+ assert_se(streq(line, "foo..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
+ assert_se(streq(line, "foo b..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+ assert_se(streq(line, "foo ba..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+ assert_se(streq(line, "foo bar..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+ assert_se(streq(line, "foo bar..."));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
+ line = mfree(line);
+
+ assert_se(ftruncate(fd, 0) >= 0);
+ assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
+
+ assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+
+ assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(streq(line, "[aaaa bbbb cccc]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+ assert_se(streq(line, "[aaaa...]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+ assert_se(streq(line, "[aaaa...]"));
+ line = mfree(line);
+
+ assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+ assert_se(streq(line, "[aaaa b...]"));
+ line = mfree(line);
+
+ safe_close(fd);
+ _exit(0);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_get_process_comm();
+ if (argc > 1) {
+ pid_t pid = 0;
+
+ (void) parse_pid(argv[1], &pid);
+ test_get_process_comm(pid);
+ } else {
+ TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1));
+ test_get_process_comm(getpid());
+ }
+
test_pid_is_unwaited();
test_pid_is_alive();
+ test_personality();
+ test_get_process_cmdline_harder();
return 0;
}
diff --git a/src/test/test-pty.c b/src/test/test-pty.c
deleted file mode 100644
index fbab3d4ebe..0000000000
--- a/src/test/test-pty.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- 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 <locale.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "pty.h"
-#include "util.h"
-#include "signal-util.h"
-
-static const char sndmsg[] = "message\n";
-static const char rcvmsg[] = "message\r\n";
-static char rcvbuf[128];
-static size_t rcvsiz = 0;
-static sd_event *event;
-
-static void run_child(Pty *pty) {
- ssize_t r, l;
- char buf[512];
-
- r = read(0, buf, sizeof(buf));
- assert_se((size_t)r == strlen(sndmsg));
- assert_se(!strncmp(buf, sndmsg, r));
-
- l = write(1, buf, r);
- assert_se(l == r);
-}
-
-static int pty_fn(Pty *pty, void *userdata, unsigned int ev, const void *ptr, size_t size) {
- switch (ev) {
- case PTY_DATA:
- assert_se(rcvsiz < strlen(rcvmsg) * 2);
- assert_se(rcvsiz + size < sizeof(rcvbuf));
-
- memcpy(&rcvbuf[rcvsiz], ptr, size);
- rcvsiz += size;
-
- if (rcvsiz >= strlen(rcvmsg) * 2) {
- assert_se(rcvsiz == strlen(rcvmsg) * 2);
- assert_se(!memcmp(rcvbuf, rcvmsg, strlen(rcvmsg)));
- assert_se(!memcmp(&rcvbuf[strlen(rcvmsg)], rcvmsg, strlen(rcvmsg)));
- }
-
- break;
- case PTY_HUP:
- /* This is guaranteed to appear _after_ the input queues are
- * drained! */
- assert_se(rcvsiz == strlen(rcvmsg) * 2);
- break;
- case PTY_CHILD:
- /* this may appear at any time */
- break;
- default:
- assert_se(0);
- break;
- }
-
- /* if we got HUP _and_ CHILD, exit */
- if (pty_get_fd(pty) < 0 && pty_get_child(pty) < 0)
- sd_event_exit(event, 0);
-
- return 0;
-}
-
-static void run_parent(Pty *pty) {
- int r;
-
- /* write message to pty, ECHO mode guarantees that we get it back
- * twice: once via ECHO, once from the run_child() fn */
- assert_se(pty_write(pty, sndmsg, strlen(sndmsg)) >= 0);
-
- r = sd_event_loop(event);
- assert_se(r >= 0);
-}
-
-static void test_pty(void) {
- pid_t pid;
- Pty *pty = NULL;
-
- rcvsiz = 0;
- zero(rcvbuf);
-
- assert_se(sd_event_default(&event) >= 0);
-
- pid = pty_fork(&pty, event, pty_fn, NULL, 80, 25);
- assert_se(pid >= 0);
-
- if (pid == 0) {
- /* child */
- run_child(pty);
- exit(0);
- }
-
- /* parent */
- run_parent(pty);
-
- /* Make sure the PTY recycled the child; yeah, this is racy if the
- * PID was already reused; but that seems fine for a test. */
- assert_se(waitpid(pid, NULL, WNOHANG) < 0 && errno == ECHILD);
-
- pty_unref(pty);
- sd_event_unref(event);
-}
-
-int main(int argc, char *argv[]) {
- unsigned int i;
-
- log_parse_environment();
- log_open();
-
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
-
- /* Oh, there're ugly races in the TTY layer regarding HUP vs IN. Turns
- * out they appear only 10% of the time. I fixed all of them and
- * don't see them, anymore. But let's be safe and run this 1000 times
- * so we catch any new ones, in case they appear again. */
- for (i = 0; i < 1000; ++i)
- test_pty();
-
- return 0;
-}
diff --git a/src/test/test-ratelimit.c b/src/test/test-ratelimit.c
index b7f6dfe246..990b834c79 100644
--- a/src/test/test-ratelimit.c
+++ b/src/test/test-ratelimit.c
@@ -19,27 +19,24 @@
#include <unistd.h>
+#include "macro.h"
#include "ratelimit.h"
#include "time-util.h"
-#include "macro.h"
static void test_ratelimit_test(void) {
int i;
RATELIMIT_DEFINE(ratelimit, 1 * USEC_PER_SEC, 10);
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 10; i++)
assert_se(ratelimit_test(&ratelimit));
- }
assert_se(!ratelimit_test(&ratelimit));
sleep(1);
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 10; i++)
assert_se(ratelimit_test(&ratelimit));
- }
RATELIMIT_INIT(ratelimit, 0, 10);
- for (i = 0; i < 10000; i++) {
+ for (i = 0; i < 10000; i++)
assert_se(ratelimit_test(&ratelimit));
- }
}
int main(int argc, char *argv[]) {
diff --git a/src/test/test-replace-var.c b/src/test/test-replace-var.c
index b1d42d77fd..297effce79 100644
--- a/src/test/test-replace-var.c
+++ b/src/test/test-replace-var.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,9 +19,10 @@
#include <string.h>
-#include "util.h"
#include "macro.h"
#include "replace-var.h"
+#include "string-util.h"
+#include "util.h"
static char *lookup(const char *variable, void *userdata) {
return strjoin("<<<", variable, ">>>", NULL);
diff --git a/src/test/test-ring.c b/src/test/test-ring.c
deleted file mode 100644
index cb8a5d4e9e..0000000000
--- a/src/test/test-ring.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- 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 <string.h>
-
-#include "def.h"
-#include "ring.h"
-
-static void test_ring(void) {
- static const char buf[8192];
- Ring r;
- size_t l;
- struct iovec vec[2];
- int s;
-
- zero(r);
-
- l = ring_peek(&r, vec);
- assert_se(l == 0);
-
- s = ring_push(&r, buf, 2048);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 2048);
-
- l = ring_peek(&r, vec);
- assert_se(l == 1);
- assert_se(vec[0].iov_len == 2048);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(ring_get_size(&r) == 2048);
-
- ring_pull(&r, 2048);
- assert_se(ring_get_size(&r) == 0);
-
- l = ring_peek(&r, vec);
- assert_se(l == 0);
- assert_se(ring_get_size(&r) == 0);
-
- s = ring_push(&r, buf, 2048);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 2048);
-
- l = ring_peek(&r, vec);
- assert_se(l == 1);
- assert_se(vec[0].iov_len == 2048);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(ring_get_size(&r) == 2048);
-
- s = ring_push(&r, buf, 1);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 2049);
-
- l = ring_peek(&r, vec);
- assert_se(l == 2);
- assert_se(vec[0].iov_len == 2048);
- assert_se(vec[1].iov_len == 1);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(!memcmp(vec[1].iov_base, buf, vec[1].iov_len));
- assert_se(ring_get_size(&r) == 2049);
-
- ring_pull(&r, 2048);
- assert_se(ring_get_size(&r) == 1);
-
- l = ring_peek(&r, vec);
- assert_se(l == 1);
- assert_se(vec[0].iov_len == 1);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(ring_get_size(&r) == 1);
-
- ring_pull(&r, 1);
- assert_se(ring_get_size(&r) == 0);
-
- s = ring_push(&r, buf, 2048);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 2048);
-
- s = ring_push(&r, buf, 2049);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 4097);
-
- l = ring_peek(&r, vec);
- assert_se(l == 1);
- assert_se(vec[0].iov_len == 4097);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(ring_get_size(&r) == 4097);
-
- ring_pull(&r, 1);
- assert_se(ring_get_size(&r) == 4096);
-
- s = ring_push(&r, buf, 4096);
- assert_se(!s);
- assert_se(ring_get_size(&r) == 8192);
-
- l = ring_peek(&r, vec);
- assert_se(l == 2);
- assert_se(vec[0].iov_len == 8191);
- assert_se(vec[1].iov_len == 1);
- assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
- assert_se(!memcmp(vec[1].iov_base, buf, vec[1].iov_len));
- assert_se(ring_get_size(&r) == 8192);
-
- ring_clear(&r);
- assert_se(ring_get_size(&r) == 0);
-}
-
-int main(int argc, char *argv[]) {
- log_parse_environment();
- log_open();
-
- test_ring();
-
- return 0;
-}
diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c
new file mode 100644
index 0000000000..62afd2de5e
--- /dev/null
+++ b/src/test/test-rlimit-util.c
@@ -0,0 +1,116 @@
+/***
+ This file is part of systemd
+
+ 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/resource.h>
+
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "macro.h"
+#include "rlimit-util.h"
+#include "string-util.h"
+#include "util.h"
+
+static void test_rlimit_parse_format(int resource, const char *string, rlim_t soft, rlim_t hard, int ret, const char *formatted) {
+ _cleanup_free_ char *f = NULL;
+ struct rlimit rl = {
+ .rlim_cur = 4711,
+ .rlim_max = 4712,
+ }, rl2 = {
+ .rlim_cur = 4713,
+ .rlim_max = 4714
+ };
+
+ assert_se(rlimit_parse(resource, string, &rl) == ret);
+ if (ret < 0)
+ return;
+
+ assert_se(rl.rlim_cur == soft);
+ assert_se(rl.rlim_max == hard);
+
+ assert_se(rlimit_format(&rl, &f) >= 0);
+ assert_se(streq(formatted, f));
+
+ assert_se(rlimit_parse(resource, formatted, &rl2) >= 0);
+ assert_se(memcmp(&rl, &rl2, sizeof(struct rlimit)) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ struct rlimit old, new, high;
+ struct rlimit err = {
+ .rlim_cur = 10,
+ .rlim_max = 5,
+ };
+
+ log_parse_environment();
+ log_open();
+
+ assert_se(drop_capability(CAP_SYS_RESOURCE) == 0);
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+ new.rlim_cur = MIN(5U, old.rlim_max);
+ new.rlim_max = old.rlim_max;
+ assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0);
+
+ assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1);
+
+ assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE"));
+ assert_se(rlimit_to_string(-1) == NULL);
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+ assert_se(setrlimit_closest(RLIMIT_NOFILE, &old) == 0);
+ assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+ assert_se(old.rlim_cur == new.rlim_cur);
+ assert_se(old.rlim_max == new.rlim_max);
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+ high = RLIMIT_MAKE_CONST(old.rlim_max == RLIM_INFINITY ? old.rlim_max : old.rlim_max + 1);
+ assert_se(setrlimit_closest(RLIMIT_NOFILE, &high) == 0);
+ assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+ assert_se(new.rlim_max == old.rlim_max);
+ assert_se(new.rlim_cur == new.rlim_max);
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+ assert_se(setrlimit_closest(RLIMIT_NOFILE, &err) == -EINVAL);
+ assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+ assert_se(old.rlim_cur == new.rlim_cur);
+ assert_se(old.rlim_max == new.rlim_max);
+
+ test_rlimit_parse_format(RLIMIT_NOFILE, "4:5", 4, 5, 0, "4:5");
+ test_rlimit_parse_format(RLIMIT_NOFILE, "6", 6, 6, 0, "6");
+ test_rlimit_parse_format(RLIMIT_NOFILE, "infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity");
+ test_rlimit_parse_format(RLIMIT_NOFILE, "infinity:infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity");
+ test_rlimit_parse_format(RLIMIT_NOFILE, "8:infinity", 8, RLIM_INFINITY, 0, "8:infinity");
+ test_rlimit_parse_format(RLIMIT_CPU, "25min:13h", (25*USEC_PER_MINUTE) / USEC_PER_SEC, (13*USEC_PER_HOUR) / USEC_PER_SEC, 0, "1500:46800");
+ test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL);
+ test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL);
+ test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL);
+ test_rlimit_parse_format(RLIMIT_NICE, "20", 20, 20, 0, "20");
+ test_rlimit_parse_format(RLIMIT_NICE, "40", 40, 40, 0, "40");
+ test_rlimit_parse_format(RLIMIT_NICE, "41", 41, 41, -ERANGE, "41");
+ test_rlimit_parse_format(RLIMIT_NICE, "0", 0, 0, 0, "0");
+ test_rlimit_parse_format(RLIMIT_NICE, "-7", 27, 27, 0, "27");
+ test_rlimit_parse_format(RLIMIT_NICE, "-20", 40, 40, 0, "40");
+ test_rlimit_parse_format(RLIMIT_NICE, "-21", 41, 41, -ERANGE, "41");
+ test_rlimit_parse_format(RLIMIT_NICE, "-0", 20, 20, 0, "20");
+ test_rlimit_parse_format(RLIMIT_NICE, "+7", 13, 13, 0, "13");
+ test_rlimit_parse_format(RLIMIT_NICE, "+19", 1, 1, 0, "1");
+ test_rlimit_parse_format(RLIMIT_NICE, "+20", 0, 0, -ERANGE, "0");
+ test_rlimit_parse_format(RLIMIT_NICE, "+0", 20, 20, 0, "20");
+
+ return 0;
+}
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index f915539e00..7b37910c33 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,10 +19,14 @@
#include <sched.h>
-#include "manager.h"
#include "macro.h"
+#include "manager.h"
+#include "rm-rf.h"
+#include "test-helper.h"
+#include "tests.h"
int main(int argc, char *argv[]) {
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
Manager *m = NULL;
Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched;
Service *ser;
@@ -32,11 +34,13 @@ 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);
- r = manager_new(MANAGER_USER, true, &m);
- if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
- printf("Skipping test: manager_new: %s", strerror(-r));
+ r = manager_new(UNIT_FILE_USER, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ log_notice_errno(r, "Skipping test: manager_new: %m");
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
new file mode 100644
index 0000000000..7545ad3764
--- /dev/null
+++ b/src/test/test-selinux.c
@@ -0,0 +1,122 @@
+/***
+ 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/stat.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "log.h"
+#include "selinux-util.h"
+#include "string-util.h"
+#include "time-util.h"
+#include "util.h"
+
+static void test_testing(void) {
+ bool b;
+
+ log_info("============ %s ==========", __func__);
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+
+ mac_selinux_retest();
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+}
+
+static void test_loading(void) {
+ usec_t n1, n2;
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ r = mac_selinux_init();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info_errno(r, "mac_selinux_init → %d (%m) %.2fs", r, (n2 - n1)/1e6);
+}
+
+static void test_cleanup(void) {
+ usec_t n1, n2;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ mac_selinux_finish();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info("mac_selinux_finish → %.2fs", (n2 - n1)/1e6);
+}
+
+static void test_misc(const char* fname) {
+ _cleanup_(mac_selinux_freep) char *label = NULL, *label2 = NULL, *label3 = NULL;
+ int r;
+ _cleanup_close_ int fd = -1;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_get_our_label(&label);
+ log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"",
+ r, strnull(label));
+
+ r = mac_selinux_get_create_label_from_exe(fname, &label2);
+ log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"",
+ r, strnull(label2));
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+
+ r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3);
+ log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"",
+ r, strnull(label3));
+}
+
+static void test_create_file_prepare(const char* fname) {
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_create_file_prepare(fname, S_IRWXU);
+ log_info_errno(r, "mac_selinux_create_file_prepare → %d (%m)", r);
+
+ mac_selinux_create_file_clear();
+}
+
+int main(int argc, char **argv) {
+ const char *path = SYSTEMD_BINARY_PATH;
+ if (argc >= 2)
+ path = argv[1];
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ test_testing();
+ test_loading();
+ test_misc(path);
+ test_create_file_prepare(path);
+ test_cleanup();
+
+ return 0;
+}
diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c
index f5bae65bef..02b8e24308 100644
--- a/src/test/test-sigbus.c
+++ b/src/test/test-sigbus.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,9 @@
#include <sys/mman.h>
-#include "util.h"
+#include "fd-util.h"
#include "sigbus.h"
+#include "util.h"
int main(int argc, char *argv[]) {
_cleanup_close_ int fd = -1;
@@ -30,6 +29,9 @@ int main(int argc, char *argv[]) {
void *addr = NULL;
uint8_t *p;
+#ifdef __SANITIZE_ADDRESS__
+ return EXIT_TEST_SKIP;
+#endif
sigbus_install();
assert_se(sigbus_pop(&addr) == 0);
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
new file mode 100644
index 0000000000..671eb869cb
--- /dev/null
+++ b/src/test/test-signal-util.c
@@ -0,0 +1,67 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 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 <signal.h>
+#include <unistd.h>
+
+#include "macro.h"
+#include "signal-util.h"
+
+static void test_block_signals(void) {
+ sigset_t ss;
+
+ assert_se(sigprocmask(0, NULL, &ss) >= 0);
+
+ assert_se(sigismember(&ss, SIGUSR1) == 0);
+ assert_se(sigismember(&ss, SIGALRM) == 0);
+ assert_se(sigismember(&ss, SIGVTALRM) == 0);
+
+ {
+ BLOCK_SIGNALS(SIGUSR1, SIGVTALRM);
+
+ assert_se(sigprocmask(0, NULL, &ss) >= 0);
+ assert_se(sigismember(&ss, SIGUSR1) == 1);
+ assert_se(sigismember(&ss, SIGALRM) == 0);
+ assert_se(sigismember(&ss, SIGVTALRM) == 1);
+
+ }
+
+ assert_se(sigprocmask(0, NULL, &ss) >= 0);
+ assert_se(sigismember(&ss, SIGUSR1) == 0);
+ assert_se(sigismember(&ss, SIGALRM) == 0);
+ assert_se(sigismember(&ss, SIGVTALRM) == 0);
+}
+
+static void test_ignore_signals(void) {
+ assert_se(ignore_signals(SIGINT, -1) >= 0);
+ assert_se(kill(getpid(), SIGINT) >= 0);
+ assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+ assert_se(kill(getpid(), SIGUSR1) >= 0);
+ assert_se(kill(getpid(), SIGUSR2) >= 0);
+ assert_se(kill(getpid(), SIGTERM) >= 0);
+ assert_se(kill(getpid(), SIGPIPE) >= 0);
+ assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_block_signals();
+ test_ignore_signals();
+
+ return 0;
+}
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
new file mode 100644
index 0000000000..b74b7ad2dd
--- /dev/null
+++ b/src/test/test-siphash24.c
@@ -0,0 +1,124 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Tom Gundersen
+
+ 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 "siphash24.h"
+#include "util.h"
+
+#define ITERATIONS 10000000ULL
+
+static void do_test(const uint8_t *in, size_t len, const uint8_t *key) {
+ struct siphash state = {};
+ uint64_t out;
+ unsigned i, j;
+
+ out = siphash24(in, len, key);
+ assert_se(out == 0xa129ca6149be45e5);
+
+ /* verify the internal state as given in the above paper */
+ siphash24_init(&state, key);
+ assert_se(state.v0 == 0x7469686173716475);
+ assert_se(state.v1 == 0x6b617f6d656e6665);
+ assert_se(state.v2 == 0x6b7f62616d677361);
+ assert_se(state.v3 == 0x7b6b696e727e6c7b);
+ siphash24_compress(in, len, &state);
+ assert_se(state.v0 == 0x4a017198de0a59e0);
+ assert_se(state.v1 == 0x0d52f6f62a4f59a4);
+ assert_se(state.v2 == 0x634cb3577b01fd3d);
+ assert_se(state.v3 == 0xa5224d6f55c7d9c8);
+ out = siphash24_finalize(&state);
+ assert_se(out == 0xa129ca6149be45e5);
+ assert_se(state.v0 == 0xf6bcd53893fecff1);
+ assert_se(state.v1 == 0x54b9964c7ea0d937);
+ assert_se(state.v2 == 0x1b38329c099bb55a);
+ assert_se(state.v3 == 0x1814bb89ad7be679);
+
+ /* verify that decomposing the input in three chunks gives the
+ same result */
+ for (i = 0; i < len; i++) {
+ for (j = i; j < len; j++) {
+ siphash24_init(&state, key);
+ siphash24_compress(in, i, &state);
+ siphash24_compress(&in[i], j - i, &state);
+ siphash24_compress(&in[j], len - j, &state);
+ out = siphash24_finalize(&state);
+ assert_se(out == 0xa129ca6149be45e5);
+ }
+ }
+}
+
+static void test_short_hashes(void) {
+ const uint8_t one[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
+ const uint8_t key[16] = { 0x22, 0x24, 0x41, 0x22, 0x55, 0x77, 0x88, 0x07,
+ 0x23, 0x09, 0x23, 0x14, 0x0c, 0x33, 0x0e, 0x0f};
+ uint8_t two[sizeof one] = {};
+
+ struct siphash state1 = {}, state2 = {};
+ unsigned i, j;
+
+ siphash24_init(&state1, key);
+ siphash24_init(&state2, key);
+
+ /* hashing 1, 2, 3, 4, 5, ..., 16 bytes, with the byte after the buffer different */
+ for (i = 1; i <= sizeof one; i++) {
+ siphash24_compress(one, i, &state1);
+
+ two[i-1] = one[i-1];
+ siphash24_compress(two, i, &state2);
+
+ assert_se(memcmp(&state1, &state2, sizeof state1) == 0);
+ }
+
+ /* hashing n and 1, n and 2, n and 3, ..., n-1 and 1, n-2 and 2, ... */
+ for (i = sizeof one; i > 0; i--) {
+ zero(two);
+
+ for (j = 1; j <= sizeof one; j++) {
+ siphash24_compress(one, i, &state1);
+ siphash24_compress(one, j, &state1);
+
+ siphash24_compress(one, i, &state2);
+ two[j-1] = one[j-1];
+ siphash24_compress(two, j, &state2);
+
+ assert_se(memcmp(&state1, &state2, sizeof state1) == 0);
+ }
+ }
+}
+
+/* see https://131002.net/siphash/siphash.pdf, Appendix A */
+int main(int argc, char *argv[]) {
+ const uint8_t in[15] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e };
+ const uint8_t key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
+ uint8_t in_buf[20];
+
+ /* Test with same input but different alignments. */
+ memcpy(in_buf, in, sizeof(in));
+ do_test(in_buf, sizeof(in), key);
+ memcpy(in_buf + 1, in, sizeof(in));
+ do_test(in_buf + 1, sizeof(in), key);
+ memcpy(in_buf + 2, in, sizeof(in));
+ do_test(in_buf + 2, sizeof(in), key);
+ memcpy(in_buf + 4, in, sizeof(in));
+ do_test(in_buf + 4, sizeof(in), key);
+
+ test_short_hashes();
+}
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
new file mode 100644
index 0000000000..8f99a13772
--- /dev/null
+++ b/src/test/test-sizeof.c
@@ -0,0 +1,53 @@
+/***
+ 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 "log.h"
+#include "time-util.h"
+
+/* Print information about various types. Useful when diagnosing
+ * gcc diagnostics on an unfamiliar architecture. */
+
+#pragma GCC diagnostic ignored "-Wtype-limits"
+
+#define info(t) \
+ log_info("%s → %zu bits%s", STRINGIFY(t), \
+ sizeof(t)*CHAR_BIT, \
+ strstr(STRINGIFY(t), "signed") ? "" : \
+ ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+
+int main(void) {
+ info(char);
+ info(signed char);
+ info(unsigned char);
+ info(short unsigned);
+ info(unsigned);
+ info(long unsigned);
+ info(long long unsigned);
+
+ info(float);
+ info(double);
+ info(long double);
+
+ info(size_t);
+ info(ssize_t);
+ info(time_t);
+ info(usec_t);
+
+ return 0;
+}
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index 4308ddfb64..97b6f3015d 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,10 +19,10 @@
#include <stdio.h>
-#include "util.h"
#include "log.h"
#include "sleep-config.h"
#include "strv.h"
+#include "util.h"
static void test_sleep(void) {
_cleanup_strv_free_ char
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index f257af445a..1f853a7f16 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -17,12 +17,38 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "socket-util.h"
+#include "alloc-util.h"
+#include "async.h"
+#include "fd-util.h"
#include "in-addr-util.h"
-#include "util.h"
-#include "macro.h"
#include "log.h"
-#include "async.h"
+#include "macro.h"
+#include "socket-util.h"
+#include "string-util.h"
+#include "util.h"
+
+static void test_ifname_valid(void) {
+ assert(ifname_valid("foo"));
+ assert(ifname_valid("eth0"));
+
+ assert(!ifname_valid("0"));
+ assert(!ifname_valid("99"));
+ assert(ifname_valid("a99"));
+ assert(ifname_valid("99a"));
+
+ assert(!ifname_valid(NULL));
+ assert(!ifname_valid(""));
+ assert(!ifname_valid(" "));
+ assert(!ifname_valid(" foo"));
+ assert(!ifname_valid("bar\n"));
+ assert(!ifname_valid("."));
+ assert(!ifname_valid(".."));
+ assert(ifname_valid("foo.bar"));
+ assert(!ifname_valid("x:y"));
+
+ assert(ifname_valid("xxxxxxxxxxxxxxx"));
+ assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
+}
static void test_socket_address_parse(void) {
SocketAddress a;
@@ -38,28 +64,25 @@ static void test_socket_address_parse(void) {
assert_se(socket_address_parse(&a, "65535") >= 0);
- if (socket_ipv6_is_supported()) {
- assert_se(socket_address_parse(&a, "[::1]") < 0);
- assert_se(socket_address_parse(&a, "[::1]8888") < 0);
- assert_se(socket_address_parse(&a, "::1") < 0);
- assert_se(socket_address_parse(&a, "[::1]:0") < 0);
- assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
- assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
+ /* The checks below will pass even if ipv6 is disabled in
+ * kernel. The underlying glibc's inet_pton() is just a string
+ * parser and doesn't make any syscalls. */
- assert_se(socket_address_parse(&a, "8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+ assert_se(socket_address_parse(&a, "[::1]") < 0);
+ assert_se(socket_address_parse(&a, "[::1]8888") < 0);
+ assert_se(socket_address_parse(&a, "::1") < 0);
+ assert_se(socket_address_parse(&a, "[::1]:0") < 0);
+ assert_se(socket_address_parse(&a, "[::1]:65536") < 0);
+ assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0);
- assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+ assert_se(socket_address_parse(&a, "8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == (socket_ipv6_is_supported() ? AF_INET6 : AF_INET));
- assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
- } else {
- assert_se(socket_address_parse(&a, "[::1]:8888") < 0);
+ assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_INET6);
- assert_se(socket_address_parse(&a, "8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET);
- }
+ assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_INET6);
assert_se(socket_address_parse(&a, "192.168.1.254:8888") >= 0);
assert_se(a.sockaddr.sa.sa_family == AF_INET);
@@ -158,6 +181,20 @@ static void test_socket_address_is_netlink(void) {
assert_se(!socket_address_is_netlink(&a, "route 1"));
}
+static void test_in_addr_is_null(void) {
+
+ union in_addr_union i = {};
+
+ assert_se(in_addr_is_null(AF_INET, &i) == true);
+ assert_se(in_addr_is_null(AF_INET6, &i) == true);
+
+ i.in.s_addr = 0x1000000;
+ assert_se(in_addr_is_null(AF_INET, &i) == false);
+ assert_se(in_addr_is_null(AF_INET6, &i) == false);
+
+ assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
+}
+
static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
union in_addr_union ua, ub;
@@ -249,6 +286,55 @@ static void test_in_addr_to_string(void) {
test_in_addr_to_string_one(AF_INET6, "fe80::");
}
+static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
+ _cleanup_free_ char *r = NULL;
+ union in_addr_union ua, uuaa;
+ int ff, ifindex2;
+
+ assert_se(in_addr_from_string(f, a, &ua) >= 0);
+ assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
+ printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
+ assert_se(streq(b, r));
+
+ assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
+ assert_se(ff == f);
+ assert_se(in_addr_equal(f, &ua, &uuaa));
+ assert_se(ifindex2 == ifindex || ifindex2 == 0);
+}
+
+static void test_in_addr_ifindex_to_string(void) {
+ test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
+ test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
+}
+
+static void test_in_addr_ifindex_from_string_auto(void) {
+ int family, ifindex;
+ union in_addr_union ua;
+
+ /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
+
+ assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
+ assert_se(family == AF_INET6);
+ assert_se(ifindex == 0);
+
+ assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
+ assert_se(family == AF_INET6);
+ assert_se(ifindex == 19);
+
+ assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
+ assert_se(family == AF_INET6);
+ assert_se(ifindex == LOOPBACK_IFINDEX);
+
+ assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
+}
+
static void *connect_thread(void *arg) {
union sockaddr_union *sa = arg;
_cleanup_close_ int fd = -1;
@@ -267,7 +353,7 @@ static void test_nameinfo_pretty(void) {
union sockaddr_union s = {
.in.sin_family = AF_INET,
.in.sin_port = 0,
- .in.sin_addr.s_addr = htonl(INADDR_ANY),
+ .in.sin_addr.s_addr = htobe32(INADDR_ANY),
};
int r;
@@ -305,17 +391,17 @@ static void test_sockaddr_equal(void) {
union sockaddr_union a = {
.in.sin_family = AF_INET,
.in.sin_port = 0,
- .in.sin_addr.s_addr = htonl(INADDR_ANY),
+ .in.sin_addr.s_addr = htobe32(INADDR_ANY),
};
union sockaddr_union b = {
.in.sin_family = AF_INET,
.in.sin_port = 0,
- .in.sin_addr.s_addr = htonl(INADDR_ANY),
+ .in.sin_addr.s_addr = htobe32(INADDR_ANY),
};
union sockaddr_union c = {
.in.sin_family = AF_INET,
.in.sin_port = 0,
- .in.sin_addr.s_addr = htonl(1234),
+ .in.sin_addr.s_addr = htobe32(1234),
};
union sockaddr_union d = {
.in6.sin6_family = AF_INET6,
@@ -329,10 +415,27 @@ static void test_sockaddr_equal(void) {
assert_se(!sockaddr_equal(&b, &c));
}
+static void test_sockaddr_un_len(void) {
+ static const struct sockaddr_un fs = {
+ .sun_family = AF_UNIX,
+ .sun_path = "/foo/bar/waldo",
+ };
+
+ static const struct sockaddr_un abstract = {
+ .sun_family = AF_UNIX,
+ .sun_path = "\0foobar",
+ };
+
+ assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path));
+ assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1));
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
+ test_ifname_valid();
+
test_socket_address_parse();
test_socket_address_parse_netlink();
test_socket_address_equal();
@@ -340,13 +443,18 @@ int main(int argc, char *argv[]) {
test_socket_address_is();
test_socket_address_is_netlink();
+ test_in_addr_is_null();
test_in_addr_prefix_intersect();
test_in_addr_prefix_next();
test_in_addr_to_string();
+ test_in_addr_ifindex_to_string();
+ test_in_addr_ifindex_from_string_auto();
test_nameinfo_pretty();
test_sockaddr_equal();
+ test_sockaddr_un_len();
+
return 0;
}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
new file mode 100644
index 0000000000..6c34250a01
--- /dev/null
+++ b/src/test/test-stat-util.c
@@ -0,0 +1,68 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+#include "stat-util.h"
+
+static void test_files_same(void) {
+ _cleanup_close_ int fd = -1;
+ char name[] = "/tmp/test-files_same.XXXXXX";
+ char name_alias[] = "/tmp/test-files_same.alias";
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_alias) >= 0);
+
+ assert_se(files_same(name, name));
+ assert_se(files_same(name, name_alias));
+
+ unlink(name);
+ unlink(name_alias);
+}
+
+static void test_is_symlink(void) {
+ char name[] = "/tmp/test-is_symlink.XXXXXX";
+ char name_link[] = "/tmp/test-is_symlink.link";
+ _cleanup_close_ int fd = -1;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_link) >= 0);
+
+ assert_se(is_symlink(name) == 0);
+ assert_se(is_symlink(name_link) == 1);
+ assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
+
+
+ unlink(name);
+ unlink(name_link);
+}
+
+int main(int argc, char *argv[]) {
+ test_files_same();
+ test_is_symlink();
+
+ return 0;
+}
diff --git a/src/test/test-strbuf.c b/src/test/test-strbuf.c
index 4ec648ae66..513218c397 100644
--- a/src/test/test-strbuf.c
+++ b/src/test/test-strbuf.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,6 +21,7 @@
#include <string.h>
#include "strbuf.h"
+#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
new file mode 100644
index 0000000000..d0f84d70bc
--- /dev/null
+++ b/src/test/test-string-util.c
@@ -0,0 +1,370 @@
+/***
+ 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 "alloc-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "strv.h"
+
+static void test_string_erase(void) {
+ char *x;
+
+ x = strdupa("");
+ assert_se(streq(string_erase(x), ""));
+
+ x = strdupa("1");
+ assert_se(streq(string_erase(x), "x"));
+
+ x = strdupa("12");
+ assert_se(streq(string_erase(x), "xx"));
+
+ x = strdupa("123");
+ assert_se(streq(string_erase(x), "xxx"));
+
+ x = strdupa("1234");
+ assert_se(streq(string_erase(x), "xxxx"));
+
+ x = strdupa("12345");
+ assert_se(streq(string_erase(x), "xxxxx"));
+
+ x = strdupa("123456");
+ assert_se(streq(string_erase(x), "xxxxxx"));
+
+ x = strdupa("1234567");
+ assert_se(streq(string_erase(x), "xxxxxxx"));
+
+ x = strdupa("12345678");
+ assert_se(streq(string_erase(x), "xxxxxxxx"));
+
+ x = strdupa("123456789");
+ assert_se(streq(string_erase(x), "xxxxxxxxx"));
+}
+
+static void test_ascii_strcasecmp_n(void) {
+
+ assert_se(ascii_strcasecmp_n("", "", 0) == 0);
+ assert_se(ascii_strcasecmp_n("", "", 1) == 0);
+ assert_se(ascii_strcasecmp_n("", "a", 1) < 0);
+ assert_se(ascii_strcasecmp_n("", "a", 2) < 0);
+ assert_se(ascii_strcasecmp_n("a", "", 1) > 0);
+ assert_se(ascii_strcasecmp_n("a", "", 2) > 0);
+ assert_se(ascii_strcasecmp_n("a", "a", 1) == 0);
+ assert_se(ascii_strcasecmp_n("a", "a", 2) == 0);
+ assert_se(ascii_strcasecmp_n("a", "b", 1) < 0);
+ assert_se(ascii_strcasecmp_n("a", "b", 2) < 0);
+ assert_se(ascii_strcasecmp_n("b", "a", 1) > 0);
+ assert_se(ascii_strcasecmp_n("b", "a", 2) > 0);
+ assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0);
+ assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0);
+ assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0);
+ assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0);
+ assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0);
+
+ assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0);
+ assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0);
+ assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0);
+ assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0);
+ assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0);
+}
+
+static void test_ascii_strcasecmp_nn(void) {
+ assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
+ assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
+ assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
+ assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0);
+
+ assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0);
+ assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0);
+ assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0);
+ assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0);
+ assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0);
+
+ assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0);
+ assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0);
+ assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
+}
+
+static void test_streq_ptr(void) {
+ assert_se(streq_ptr(NULL, NULL));
+ assert_se(!streq_ptr("abc", "cdef"));
+}
+
+static void test_strstrip(void) {
+ char *r;
+ char input[] = " hello, waldo. ";
+
+ r = strstrip(input);
+ assert_se(streq(r, "hello, waldo."));
+}
+
+static void test_strextend(void) {
+ _cleanup_free_ char *str = strdup("0123");
+ strextend(&str, "456", "78", "9", NULL);
+ assert_se(streq(str, "0123456789"));
+}
+
+static void test_strrep(void) {
+ _cleanup_free_ char *one, *three, *zero;
+ one = strrep("waldo", 1);
+ three = strrep("waldo", 3);
+ zero = strrep("waldo", 0);
+
+ assert_se(streq(one, "waldo"));
+ assert_se(streq(three, "waldowaldowaldo"));
+ assert_se(streq(zero, ""));
+}
+
+
+static void test_strappend(void) {
+ _cleanup_free_ char *t1, *t2, *t3, *t4;
+
+ t1 = strappend(NULL, NULL);
+ assert_se(streq(t1, ""));
+
+ t2 = strappend(NULL, "suf");
+ assert_se(streq(t2, "suf"));
+
+ t3 = strappend("pre", NULL);
+ assert_se(streq(t3, "pre"));
+
+ t4 = strappend("pre", "suf");
+ assert_se(streq(t4, "presuf"));
+}
+
+static void test_string_has_cc(void) {
+ assert_se(string_has_cc("abc\1", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t\a"));
+
+ assert_se(!string_has_cc("abc\t\t", "\t"));
+ assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
+ assert_se(!string_has_cc("a\ab\tc", "\t\a"));
+}
+
+static void test_ascii_strlower(void) {
+ char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
+ assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
+}
+
+static void test_strshorten(void) {
+ char s[] = "foobar";
+
+ assert_se(strlen(strshorten(s, 6)) == 6);
+ assert_se(strlen(strshorten(s, 12)) == 6);
+ assert_se(strlen(strshorten(s, 2)) == 2);
+ assert_se(strlen(strshorten(s, 0)) == 0);
+}
+
+static void test_strjoina(void) {
+ char *actual;
+
+ actual = strjoina("", "foo", "bar");
+ assert_se(streq(actual, "foobar"));
+
+ actual = strjoina("foo", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ 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_strcmp_ptr(void) {
+ assert_se(strcmp_ptr(NULL, NULL) == 0);
+ assert_se(strcmp_ptr("", NULL) > 0);
+ assert_se(strcmp_ptr("foo", NULL) > 0);
+ assert_se(strcmp_ptr(NULL, "") < 0);
+ assert_se(strcmp_ptr(NULL, "bar") < 0);
+ assert_se(strcmp_ptr("foo", "bar") > 0);
+ assert_se(strcmp_ptr("bar", "baz") < 0);
+ assert_se(strcmp_ptr("foo", "foo") == 0);
+ assert_se(strcmp_ptr("", "") == 0);
+}
+
+static void test_foreach_word(void) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+ const char test[] = "test abc d\te f ";
+ const char * const expected[] = {
+ "test",
+ "abc",
+ "d",
+ "e",
+ "f",
+ "",
+ NULL
+ };
+
+ FOREACH_WORD(word, l, test, state)
+ assert_se(strneq(expected[i++], word, l));
+}
+
+static void check(const char *test, char** expected, bool trailing) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+
+ printf("<<<%s>>>\n", test);
+ FOREACH_WORD_QUOTED(word, l, test, state) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = strndup(word, l));
+ assert_se(strneq(expected[i++], word, l));
+ printf("<%s>\n", t);
+ }
+ 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_endswith(void) {
+ assert_se(endswith("foobar", "bar"));
+ assert_se(endswith("foobar", ""));
+ assert_se(endswith("foobar", "foobar"));
+ assert_se(endswith("", ""));
+
+ assert_se(!endswith("foobar", "foo"));
+ assert_se(!endswith("foobar", "foobarfoofoo"));
+}
+
+static void test_endswith_no_case(void) {
+ assert_se(endswith_no_case("fooBAR", "bar"));
+ assert_se(endswith_no_case("foobar", ""));
+ assert_se(endswith_no_case("foobar", "FOOBAR"));
+ assert_se(endswith_no_case("", ""));
+
+ assert_se(!endswith_no_case("foobar", "FOO"));
+ assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
+}
+
+static void test_delete_chars(void) {
+ char *r;
+ char input[] = " hello, waldo. abc";
+
+ r = delete_chars(input, WHITESPACE);
+ assert_se(streq(r, "hello,waldo.abc"));
+}
+
+static void test_in_charset(void) {
+ assert_se(in_charset("dddaaabbbcccc", "abcd"));
+ assert_se(!in_charset("dddaaabbbcccc", "abc f"));
+}
+
+static void test_split_pair(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+
+ assert_se(split_pair("", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
+ assert_se(streq(a, "foo"));
+ assert_se(streq(b, "bar"));
+ free(a);
+ free(b);
+ assert_se(split_pair("==", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, ""));
+ free(a);
+ free(b);
+
+ assert_se(split_pair("===", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, "="));
+}
+
+static void test_first_word(void) {
+ assert_se(first_word("Hello", ""));
+ assert_se(first_word("Hello", "Hello"));
+ assert_se(first_word("Hello world", "Hello"));
+ assert_se(first_word("Hello\tworld", "Hello"));
+ assert_se(first_word("Hello\nworld", "Hello"));
+ assert_se(first_word("Hello\rworld", "Hello"));
+ assert_se(first_word("Hello ", "Hello"));
+
+ assert_se(!first_word("Hello", "Hellooo"));
+ assert_se(!first_word("Hello", "xxxxx"));
+ assert_se(!first_word("Hellooo", "Hello"));
+}
+
+int main(int argc, char *argv[]) {
+ test_string_erase();
+ test_ascii_strcasecmp_n();
+ test_ascii_strcasecmp_nn();
+ test_streq_ptr();
+ test_strstrip();
+ test_strextend();
+ test_strrep();
+ test_strappend();
+ test_string_has_cc();
+ test_ascii_strlower();
+ test_strshorten();
+ test_strjoina();
+ test_strcmp_ptr();
+ test_foreach_word();
+ test_foreach_word_quoted();
+ test_endswith();
+ test_endswith_no_case();
+ test_delete_chars();
+ test_in_charset();
+ test_split_pair();
+ test_first_word();
+
+ return 0;
+}
diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c
index 358454842a..72b0f6fc11 100644
--- a/src/test/test-strip-tab-ansi.c
+++ b/src/test/test-strip-tab-ansi.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,9 @@
#include <stdio.h>
-#include "util.h"
+#include "string-util.h"
#include "terminal-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
char *p;
@@ -33,13 +32,13 @@ int main(int argc, char *argv[]) {
assert_se(streq(p, " Foobar bar waldo "));
free(p);
- assert_se(p = strdup(ANSI_HIGHLIGHT_ON "Hello" ANSI_HIGHLIGHT_OFF ANSI_HIGHLIGHT_RED_ON " world!" ANSI_HIGHLIGHT_OFF));
+ assert_se(p = strdup(ANSI_HIGHLIGHT "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL));
assert_se(strip_tab_ansi(&p, NULL));
fprintf(stdout, "<%s>\n", p);
assert_se(streq(p, "Hello world!"));
free(p);
- assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT_ON "\x1B[" "Hello" ANSI_HIGHLIGHT_OFF ANSI_HIGHLIGHT_RED_ON " world!" ANSI_HIGHLIGHT_OFF));
+ assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT "\x1B[" "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL));
assert_se(strip_tab_ansi(&p, NULL));
assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!"));
free(p);
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index d5ea2b3fab..88da69e2d7 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,9 +20,11 @@
#include <string.h>
-#include "util.h"
+#include "alloc-util.h"
#include "specifier.h"
+#include "string-util.h"
#include "strv.h"
+#include "util.h"
static void test_specifier_printf(void) {
static const Specifier table[] = {
@@ -54,6 +54,25 @@ static void test_specifier_printf(void) {
puts(w);
}
+static void test_str_in_set(void) {
+ assert_se(STR_IN_SET("x", "x", "y", "z"));
+ assert_se(!STR_IN_SET("X", "x", "y", "z"));
+ assert_se(!STR_IN_SET("", "x", "y", "z"));
+ assert_se(STR_IN_SET("x", "w", "x"));
+}
+
+static void test_strptr_in_set(void) {
+ assert_se(STRPTR_IN_SET("x", "x", "y", "z"));
+ assert_se(!STRPTR_IN_SET("X", "x", "y", "z"));
+ assert_se(!STRPTR_IN_SET("", "x", "y", "z"));
+ assert_se(STRPTR_IN_SET("x", "w", "x"));
+
+ assert_se(!STRPTR_IN_SET(NULL, "x", "y", "z"));
+ assert_se(!STRPTR_IN_SET(NULL, ""));
+ /* strv cannot contain a null, hence the result below */
+ assert_se(!STRPTR_IN_SET(NULL, NULL));
+}
+
static const char* const input_table_multiple[] = {
"one",
"two",
@@ -70,6 +89,18 @@ static const char* const input_table_none[] = {
NULL,
};
+static const char* const input_table_two_empties[] = {
+ "",
+ "",
+ NULL,
+};
+
+static const char* const input_table_one_empty[] = {
+ "",
+ NULL,
+};
+
+
static const char* const input_table_quotes[] = {
"\"",
"'",
@@ -130,7 +161,7 @@ static void test_strv_find_startswith(void) {
}
static void test_strv_join(void) {
- _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL;
+ _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
p = strv_join((char **)input_table_multiple, ", ");
assert_se(p);
@@ -151,11 +182,19 @@ static void test_strv_join(void) {
t = strv_join((char **)input_table_none, ", ");
assert_se(t);
assert_se(streq(t, ""));
+
+ v = strv_join((char **)input_table_two_empties, ", ");
+ assert_se(v);
+ assert_se(streq(v, ", "));
+
+ w = strv_join((char **)input_table_one_empty, ", ");
+ assert_se(w);
+ assert_se(streq(w, ""));
}
static void test_strv_quote_unquote(const char* const *split, const char *quoted) {
_cleanup_free_ char *p;
- _cleanup_strv_free_ char **s;
+ _cleanup_strv_free_ char **s = NULL;
char **t;
int r;
@@ -165,8 +204,8 @@ static void test_strv_quote_unquote(const char* const *split, const char *quoted
assert_se(p);
assert_se(streq(p, quoted));
- r = strv_split_quoted(&s, quoted, 0);
- assert_se(r == 0);
+ r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES);
+ assert_se(r == (int) strv_length(s));
assert_se(s);
STRV_FOREACH(t, s) {
assert_se(*t);
@@ -182,8 +221,8 @@ static void test_strv_unquote(const char *quoted, char **list) {
char **t;
int r;
- r = strv_split_quoted(&s, quoted, 0);
- assert_se(r == 0);
+ r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES);
+ assert_se(r == (int) strv_length(list));
assert_se(s);
j = strv_join(s, " | ");
assert_se(j);
@@ -199,7 +238,7 @@ static void test_invalid_unquote(const char *quoted) {
char **s = NULL;
int r;
- r = strv_split_quoted(&s, quoted, 0);
+ r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES);
assert_se(s == NULL);
assert_se(r == -EINVAL);
}
@@ -219,6 +258,21 @@ static void test_strv_split(void) {
}
}
+static void test_strv_split_extract(void) {
+ _cleanup_strv_free_ char **l = NULL;
+ const char *str = ":foo\\:bar::waldo:";
+ int r;
+
+ r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+ assert_se(r == (int) strv_length(l));
+ assert_se(streq_ptr(l[0], ""));
+ assert_se(streq_ptr(l[1], "foo:bar"));
+ assert_se(streq_ptr(l[2], ""));
+ assert_se(streq_ptr(l[3], "waldo"));
+ assert_se(streq_ptr(l[4], ""));
+ assert_se(streq_ptr(l[5], NULL));
+}
+
static void test_strv_split_newlines(void) {
unsigned i = 0;
char **s;
@@ -307,7 +361,7 @@ static void test_strv_sort(void) {
}
static void test_strv_extend_strv_concat(void) {
- _cleanup_strv_free_ char **a = NULL, **b = NULL;
+ _cleanup_strv_free_ char **a = NULL, **b = NULL;
a = strv_new("without", "suffix", NULL);
b = strv_new("with", "suffix", NULL);
@@ -323,14 +377,14 @@ static void test_strv_extend_strv_concat(void) {
}
static void test_strv_extend_strv(void) {
- _cleanup_strv_free_ char **a = NULL, **b = NULL;
+ _cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL;
a = strv_new("abc", "def", "ghi", NULL);
- b = strv_new("jkl", "mno", "pqr", NULL);
+ b = strv_new("jkl", "mno", "abc", "pqr", NULL);
assert_se(a);
assert_se(b);
- assert_se(strv_extend_strv(&a, b) >= 0);
+ assert_se(strv_extend_strv(&a, b, true) == 3);
assert_se(streq(a[0], "abc"));
assert_se(streq(a[1], "def"));
@@ -338,8 +392,14 @@ static void test_strv_extend_strv(void) {
assert_se(streq(a[3], "jkl"));
assert_se(streq(a[4], "mno"));
assert_se(streq(a[5], "pqr"));
-
assert_se(strv_length(a) == 6);
+
+ assert_se(strv_extend_strv(&n, b, false) >= 0);
+ assert_se(streq(n[0], "jkl"));
+ assert_se(streq(n[1], "mno"));
+ assert_se(streq(n[2], "abc"));
+ assert_se(streq(n[3], "pqr"));
+ assert_se(strv_length(n) == 4);
}
static void test_strv_extend(void) {
@@ -393,9 +453,14 @@ static void test_strv_foreach_backwards(void) {
assert_se(a);
- STRV_FOREACH_BACKWARDS(check, a) {
+ STRV_FOREACH_BACKWARDS(check, a)
assert_se(streq_ptr(*check, input_table_multiple[i--]));
- }
+
+ STRV_FOREACH_BACKWARDS(check, (char**) NULL)
+ assert_not_reached("Let's see that we check empty strv right, too.");
+
+ STRV_FOREACH_BACKWARDS(check, (char**) { NULL })
+ assert_not_reached("Let's see that we check empty strv right, too.");
}
static void test_strv_foreach_pair(void) {
@@ -542,8 +607,128 @@ static void test_strv_reverse(void) {
assert_se(streq_ptr(d[3], NULL));
}
+static void test_strv_shell_escape(void) {
+ _cleanup_strv_free_ char **v = NULL;
+
+ v = strv_new("foo:bar", "bar,baz", "wal\\do", NULL);
+ assert_se(v);
+ assert_se(strv_shell_escape(v, ",:"));
+ assert_se(streq_ptr(v[0], "foo\\:bar"));
+ assert_se(streq_ptr(v[1], "bar\\,baz"));
+ assert_se(streq_ptr(v[2], "wal\\\\do"));
+ assert_se(streq_ptr(v[3], NULL));
+}
+
+static void test_strv_skip_one(char **a, size_t n, char **b) {
+ a = strv_skip(a, n);
+ assert_se(strv_equal(a, b));
+}
+
+static void test_strv_skip(void) {
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL));
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL));
+ test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL));
+
+ test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
+ test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL));
+ test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL));
+
+ test_strv_skip_one(STRV_MAKE(NULL), 0, STRV_MAKE(NULL));
+ test_strv_skip_one(STRV_MAKE(NULL), 1, STRV_MAKE(NULL));
+ test_strv_skip_one(STRV_MAKE(NULL), 55, STRV_MAKE(NULL));
+}
+
+static void test_strv_extend_n(void) {
+ _cleanup_strv_free_ char **v = NULL;
+
+ v = strv_new("foo", "bar", NULL);
+ assert_se(v);
+
+ assert_se(strv_extend_n(&v, "waldo", 3) >= 0);
+ assert_se(strv_extend_n(&v, "piep", 2) >= 0);
+
+ assert_se(streq(v[0], "foo"));
+ assert_se(streq(v[1], "bar"));
+ assert_se(streq(v[2], "waldo"));
+ assert_se(streq(v[3], "waldo"));
+ assert_se(streq(v[4], "waldo"));
+ assert_se(streq(v[5], "piep"));
+ assert_se(streq(v[6], "piep"));
+ assert_se(v[7] == NULL);
+
+ v = strv_free(v);
+
+ assert_se(strv_extend_n(&v, "foo", 1) >= 0);
+ assert_se(strv_extend_n(&v, "bar", 0) >= 0);
+
+ assert_se(streq(v[0], "foo"));
+ assert_se(v[1] == NULL);
+}
+
+static void test_strv_make_nulstr_one(char **l) {
+ _cleanup_free_ char *b = NULL, *c = NULL;
+ _cleanup_strv_free_ char **q = NULL;
+ const char *s = NULL;
+ size_t n, m;
+ unsigned i = 0;
+
+ assert_se(strv_make_nulstr(l, &b, &n) >= 0);
+ assert_se(q = strv_parse_nulstr(b, n));
+ assert_se(strv_equal(l, q));
+
+ assert_se(strv_make_nulstr(q, &c, &m) >= 0);
+ assert_se(m == n);
+ assert_se(memcmp(b, c, m) == 0);
+
+ NULSTR_FOREACH(s, b)
+ assert_se(streq(s, l[i++]));
+ assert_se(i == strv_length(l));
+}
+
+static void test_strv_make_nulstr(void) {
+ test_strv_make_nulstr_one(NULL);
+ test_strv_make_nulstr_one(STRV_MAKE(NULL));
+ test_strv_make_nulstr_one(STRV_MAKE("foo"));
+ test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
+ test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
+}
+
+static void test_foreach_string(void) {
+ const char * const t[] = {
+ "foo",
+ "bar",
+ "waldo",
+ NULL
+ };
+ const char *x;
+ unsigned i = 0;
+
+ FOREACH_STRING(x, "foo", "bar", "waldo")
+ assert_se(streq_ptr(t[i++], x));
+
+ assert_se(i == 3);
+
+ FOREACH_STRING(x, "zzz")
+ assert_se(streq(x, "zzz"));
+}
+
+static void test_strv_fnmatch(void) {
+ _cleanup_strv_free_ char **v = NULL;
+
+ assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0));
+
+ v = strv_new("*\\*", NULL);
+ assert_se(!strv_fnmatch(v, "\\", 0));
+ assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE));
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
+ test_str_in_set();
+ test_strptr_in_set();
test_strv_foreach();
test_strv_foreach_backwards();
test_strv_foreach_pair();
@@ -555,6 +740,8 @@ int main(int argc, char *argv[]) {
test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
test_strv_quote_unquote(input_table_one, "\"one\"");
test_strv_quote_unquote(input_table_none, "");
+ test_strv_quote_unquote(input_table_one_empty, "\"\"");
+ test_strv_quote_unquote(input_table_two_empties, "\"\" \"\"");
test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
@@ -583,6 +770,7 @@ int main(int argc, char *argv[]) {
test_invalid_unquote("'x'y'g");
test_strv_split();
+ test_strv_split_extract();
test_strv_split_newlines();
test_strv_split_nulstr();
test_strv_parse_nulstr();
@@ -598,6 +786,13 @@ int main(int argc, char *argv[]) {
test_strv_equal();
test_strv_is_uniq();
test_strv_reverse();
+ test_strv_shell_escape();
+ test_strv_skip();
+ test_strv_extend_n();
+ test_strv_make_nulstr();
+
+ test_foreach_string();
+ test_strv_fnmatch();
return 0;
}
diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c
index 858a4081da..9bea770131 100644
--- a/src/test/test-strxcpyx.c
+++ b/src/test/test-strxcpyx.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,9 @@
#include <string.h>
-#include "util.h"
+#include "string-util.h"
#include "strxcpyx.h"
+#include "util.h"
static void test_strpcpy(void) {
char target[25];
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 0e5ab1645f..0be74921fc 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -17,7 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "architecture.h"
#include "automount.h"
+#include "busname.h"
#include "cgroup.h"
#include "compress.h"
#include "condition.h"
@@ -25,31 +27,27 @@
#include "execute.h"
#include "install.h"
#include "job.h"
+#include "journald-server.h"
#include "kill.h"
+#include "link-config.h"
+#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
#include "mount.h"
#include "path.h"
+#include "rlimit-util.h"
#include "scope.h"
#include "service.h"
#include "slice.h"
-#include "snapshot.h"
#include "socket-util.h"
#include "socket.h"
#include "swap.h"
#include "target.h"
+#include "test-tables.h"
#include "timer.h"
#include "unit-name.h"
#include "unit.h"
#include "util.h"
-#include "architecture.h"
-#include "link-config.h"
-#include "bus-xml-policy.h"
-#include "busname.h"
-#include "journald-server.h"
-#include "locale-util.h"
-
-#include "test-tables.h"
int main(int argc, char **argv) {
test_table(architecture, ARCHITECTURE);
@@ -84,8 +82,6 @@ int main(int argc, char **argv) {
test_table(path_result, PATH_RESULT);
test_table(path_state, PATH_STATE);
test_table(path_type, PATH_TYPE);
- test_table(policy_item_class, POLICY_ITEM_CLASS);
- test_table(policy_item_type, POLICY_ITEM_TYPE);
test_table(protect_home, PROTECT_HOME);
test_table(protect_system, PROTECT_SYSTEM);
test_table(rlimit, RLIMIT);
@@ -97,7 +93,6 @@ int main(int argc, char **argv) {
test_table(service_state, SERVICE_STATE);
test_table(service_type, SERVICE_TYPE);
test_table(slice_state, SLICE_STATE);
- test_table(snapshot_state, SNAPSHOT_STATE);
test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY);
test_table(socket_exec_command, SOCKET_EXEC_COMMAND);
test_table(socket_result, SOCKET_RESULT);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index d81fdb9923..373a1b70ba 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -18,13 +18,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
-#include "terminal-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "log.h"
#include "macro.h"
+#include "terminal-util.h"
#include "util.h"
-#include "log.h"
static void test_default_term_for_tty(void) {
puts(default_term_for_tty("/dev/tty23"));
@@ -48,7 +50,7 @@ static void test_read_one_char(void) {
char name[] = "/tmp/test-read_one_char.XXXXXX";
int fd;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
file = fdopen(fd, "r+");
assert_se(file);
diff --git a/src/test/test-time.c b/src/test/test-time.c
index 3840fff061..7078a0374d 100644
--- a/src/test/test-time.c
+++ b/src/test/test-time.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "time-util.h"
#include "strv.h"
+#include "time-util.h"
+#include "random-util.h"
static void test_parse_sec(void) {
usec_t u;
@@ -57,6 +56,28 @@ static void test_parse_sec(void) {
assert_se(parse_sec(".3 infinity", &u) < 0);
}
+static void test_parse_time(void) {
+ usec_t u;
+
+ assert_se(parse_time("5", &u, 1) >= 0);
+ assert_se(u == 5);
+
+ assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0);
+ assert_se(u == 5 * USEC_PER_MSEC);
+
+ assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, 1) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
+ assert_se(u == 5 * USEC_PER_SEC);
+}
+
static void test_parse_nsec(void) {
nsec_t u;
@@ -154,19 +175,97 @@ static void test_get_timezones(void) {
r = get_timezones(&zones);
assert_se(r == 0);
- STRV_FOREACH(zone, zones) {
+ STRV_FOREACH(zone, zones)
assert_se(timezone_is_valid(*zone));
+}
+
+static void test_usec_add(void) {
+ assert_se(usec_add(0, 0) == 0);
+ assert_se(usec_add(1, 4) == 5);
+ assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY);
+ assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY);
+ assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3);
+ assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY);
+ assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY);
+ assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY);
+}
+
+static void test_usec_sub(void) {
+ assert_se(usec_sub(0, 0) == 0);
+ assert_se(usec_sub(4, 1) == 3);
+ assert_se(usec_sub(4, 4) == 0);
+ assert_se(usec_sub(4, 5) == 0);
+ assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY);
+ assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY);
+ assert_se(usec_sub(USEC_INFINITY-3, -4) == USEC_INFINITY);
+ assert_se(usec_sub(USEC_INFINITY-3, -5) == USEC_INFINITY);
+ assert_se(usec_sub(USEC_INFINITY, 5) == USEC_INFINITY);
+}
+
+static void test_format_timestamp(void) {
+ unsigned i;
+
+ for (i = 0; i < 100; i++) {
+ char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
+ usec_t x, y;
+
+ random_bytes(&x, sizeof(x));
+ x = x % (2147483600 * USEC_PER_SEC) + 1;
+
+ assert_se(format_timestamp(buf, sizeof(buf), x));
+ log_info("%s", buf);
+ assert_se(parse_timestamp(buf, &y) >= 0);
+ assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
+
+ assert_se(format_timestamp_utc(buf, sizeof(buf), x));
+ log_info("%s", buf);
+ assert_se(parse_timestamp(buf, &y) >= 0);
+ assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
+
+ assert_se(format_timestamp_us(buf, sizeof(buf), x));
+ log_info("%s", buf);
+ assert_se(parse_timestamp(buf, &y) >= 0);
+ assert_se(x == y);
+
+ assert_se(format_timestamp_us_utc(buf, sizeof(buf), x));
+ log_info("%s", buf);
+ assert_se(parse_timestamp(buf, &y) >= 0);
+ assert_se(x == y);
+
+ assert_se(format_timestamp_relative(buf, sizeof(buf), x));
+ log_info("%s", buf);
+ assert_se(parse_timestamp(buf, &y) >= 0);
+
+ /* The two calls above will run with a slightly different local time. Make sure we are in the same
+ * range however, but give enough leeway that this is unlikely to explode. And of course,
+ * format_timestamp_relative() scales the accuracy with the distance from the current time up to one
+ * month, cover for that too. */
+ assert_se(y > x ? y - x : x - y <= USEC_PER_MONTH + USEC_PER_DAY);
}
}
int main(int argc, char *argv[]) {
+ uintmax_t x;
+
test_parse_sec();
+ test_parse_time();
test_parse_nsec();
test_format_timespan(1);
test_format_timespan(USEC_PER_MSEC);
test_format_timespan(USEC_PER_SEC);
test_timezone_is_valid();
test_get_timezones();
+ test_usec_add();
+ test_usec_sub();
+ test_format_timestamp();
+
+ /* Ensure time_t is signed */
+ assert_cc((time_t) -1 < (time_t) 1);
+
+ /* Ensure TIME_T_MAX works correctly */
+ x = (uintmax_t) TIME_T_MAX;
+ x++;
+ assert((time_t) x < 0);
return 0;
}
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 221dd67eb2..f35e6793b7 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,31 +18,64 @@
***/
#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
-#include "util.h"
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
+#include "log.h"
+#include "string-util.h"
+#include "util.h"
int main(int argc, char** argv) {
+ _cleanup_free_ char *cmd = NULL, *cmd2 = NULL, *ans = NULL, *ans2 = NULL, *d = NULL, *tmp = NULL, *line = NULL;
+ _cleanup_close_ int fd = -1, fd2 = -1;
const char *p = argv[1] ?: "/tmp";
- char *pattern = strjoina(p, "/systemd-test-XXXXXX");
- _cleanup_close_ int fd, fd2;
- _cleanup_free_ char *cmd, *cmd2;
+ char *pattern;
- fd = open_tmpfile(p, O_RDWR|O_CLOEXEC);
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ pattern = strjoina(p, "/systemd-test-XXXXXX");
+
+ fd = open_tmpfile_unlinkable(p, O_RDWR|O_CLOEXEC);
assert_se(fd >= 0);
assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd) > 0);
- system(cmd);
+ (void) system(cmd);
+ assert_se(readlink_malloc(cmd + 6, &ans) >= 0);
+ log_debug("link1: %s", ans);
+ assert_se(endswith(ans, " (deleted)"));
- fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC);
+ fd2 = mkostemp_safe(pattern);
assert_se(fd >= 0);
assert_se(unlink(pattern) == 0);
assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd2) > 0);
- system(cmd2);
+ (void) system(cmd2);
+ assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0);
+ log_debug("link2: %s", ans2);
+ assert_se(endswith(ans2, " (deleted)"));
+
+ pattern = strjoina(p, "/tmpfiles-test");
+ assert_se(tempfn_random(pattern, NULL, &d) >= 0);
+
+ fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp);
+ assert_se(fd >= 0);
+ assert_se(write(fd, "foobar\n", 7) == 7);
+
+ assert_se(touch(d) >= 0);
+ assert_se(link_tmpfile(fd, tmp, d) == -EEXIST);
+ assert_se(unlink(d) >= 0);
+ assert_se(link_tmpfile(fd, tmp, d) >= 0);
+
+ assert_se(read_one_line_file(d, &line) >= 0);
+ assert_se(streq(line, "foobar"));
+ assert_se(unlink(d) >= 0);
return 0;
}
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 2b765a3e90..e965b4494a 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -18,58 +18,53 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
-#include <unistd.h>
#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <sys/mount.h>
#include <sys/signalfd.h>
+#include <unistd.h>
+#include "fs-util.h"
+#include "log.h"
#include "missing.h"
#include "selinux-util.h"
#include "signal-util.h"
-#include "udev.h"
+#include "string-util.h"
#include "udev-util.h"
+#include "udev.h"
static int fake_filesystems(void) {
static const struct fakefs {
const char *src;
const char *target;
const char *error;
+ bool ignore_mount_error;
} fakefss[] = {
- { "test/sys", "/sys", "failed to mount test /sys" },
- { "test/dev", "/dev", "failed to mount test /dev" },
- { "test/run", "/run", "failed to mount test /run" },
- { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
- { "test/run", "/usr/lib/udev/rules.d", "failed to mount empty /usr/lib/udev/rules.d" },
+ { "test/tmpfs/sys", "/sys", "failed to mount test /sys", false },
+ { "test/tmpfs/dev", "/dev", "failed to mount test /dev", false },
+ { "test/run", "/run", "failed to mount test /run", false },
+ { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d", true },
+ { "test/run", UDEVLIBEXECDIR "/rules.d", "failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
};
unsigned int i;
- int err;
- err = unshare(CLONE_NEWNS);
- if (err < 0) {
- err = -errno;
- fprintf(stderr, "failed to call unshare(): %m\n");
- goto out;
- }
+ if (unshare(CLONE_NEWNS) < 0)
+ return log_error_errno(errno, "failed to call unshare(): %m");
- if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
- err = -errno;
- fprintf(stderr, "failed to mount / as private: %m\n");
- goto out;
- }
+ if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
+ return log_error_errno(errno, "failed to mount / as private: %m");
for (i = 0; i < ELEMENTSOF(fakefss); i++) {
- err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
- if (err < 0) {
- err = -errno;
- fprintf(stderr, "%s %m", fakefss[i].error);
- return err;
+ if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
+ log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
+ if (!fakefss[i].ignore_mount_error)
+ return -errno;
}
}
-out:
- return err;
+
+ return 0;
}
int main(int argc, char *argv[]) {
@@ -82,6 +77,9 @@ int main(int argc, char *argv[]) {
const char *action;
int err;
+ log_parse_environment();
+ log_open();
+
err = fake_filesystems();
if (err < 0)
return EXIT_FAILURE;
@@ -91,7 +89,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
log_debug("version %s", VERSION);
- mac_selinux_init("/dev");
+ mac_selinux_init();
action = argv[1];
if (action == NULL) {
diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c
index bc5baa2fcb..41f06a5cec 100644
--- a/src/test/test-uid-range.c
+++ b/src/test/test-uid-range.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,10 @@
#include <stddef.h>
-#include "util.h"
+#include "alloc-util.h"
#include "uid-range.h"
+#include "user-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
_cleanup_free_ UidRange *p = NULL;
diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c
index 1754d06b2d..4f64398943 100644
--- a/src/test/test-unaligned.c
+++ b/src/test/test-unaligned.c
@@ -17,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unaligned.h"
#include "sparse-endian.h"
+#include "unaligned.h"
#include "util.h"
static uint8_t data[] = {
@@ -26,7 +26,7 @@ static uint8_t data[] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
};
-int main(int argc, const char *argv[]) {
+static void test_be(void) {
uint8_t scratch[16];
assert_se(unaligned_read_be16(&data[0]) == 0x0001);
@@ -91,3 +91,99 @@ int main(int argc, const char *argv[]) {
unaligned_write_be64(&scratch[7], 0x0708090a0b0c0d0e);
assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0);
}
+
+static void test_le(void) {
+ uint8_t scratch[16];
+
+ assert_se(unaligned_read_le16(&data[0]) == 0x0100);
+ assert_se(unaligned_read_le16(&data[1]) == 0x0201);
+
+ assert_se(unaligned_read_le32(&data[0]) == 0x03020100);
+ assert_se(unaligned_read_le32(&data[1]) == 0x04030201);
+ assert_se(unaligned_read_le32(&data[2]) == 0x05040302);
+ assert_se(unaligned_read_le32(&data[3]) == 0x06050403);
+
+ assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100);
+ assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201);
+ assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302);
+ assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403);
+ assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504);
+ assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605);
+ assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706);
+ assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807);
+
+ zero(scratch);
+ unaligned_write_le16(&scratch[0], 0x0100);
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0);
+ zero(scratch);
+ unaligned_write_le16(&scratch[1], 0x0201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0);
+
+ zero(scratch);
+ unaligned_write_le32(&scratch[0], 0x03020100);
+
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[1], 0x04030201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[2], 0x05040302);
+ assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0);
+ zero(scratch);
+ unaligned_write_le32(&scratch[3], 0x06050403);
+ assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0);
+
+ zero(scratch);
+ unaligned_write_le64(&scratch[0], 0x0706050403020100);
+ assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[1], 0x0807060504030201);
+ assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[2], 0x0908070605040302);
+ assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[3], 0x0a09080706050403);
+ assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[4], 0x0B0A090807060504);
+ assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605);
+ assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706);
+ assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0);
+ zero(scratch);
+ unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807);
+ assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0);
+}
+
+static void test_ne(void) {
+ uint16_t x = 4711;
+ uint32_t y = 123456;
+ uint64_t z = 9876543210;
+
+ /* Note that we don't bother actually testing alignment issues in this function, after all the _ne() functions
+ * are just aliases for the _le() or _be() implementations, which we test extensively above. Hence, in this
+ * function, just ensure that they map to the right version on the local architecture. */
+
+ assert_se(unaligned_read_ne16(&x) == 4711);
+ assert_se(unaligned_read_ne32(&y) == 123456);
+ assert_se(unaligned_read_ne64(&z) == 9876543210);
+
+ unaligned_write_ne16(&x, 1);
+ unaligned_write_ne32(&y, 2);
+ unaligned_write_ne64(&z, 3);
+
+ assert_se(x == 1);
+ assert_se(y == 2);
+ assert_se(z == 3);
+}
+
+int main(int argc, const char *argv[]) {
+ test_be();
+ test_le();
+ test_ne();
+ return 0;
+}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 8358789e6f..7ef087a2e3 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,23 +18,31 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
+#include <fcntl.h>
#include <stddef.h>
+#include <stdio.h>
#include <string.h>
+#include <sys/capability.h>
#include <unistd.h>
-#include <fcntl.h>
-#include "install.h"
-#include "install-printf.h"
-#include "specifier.h"
-#include "util.h"
-#include "macro.h"
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "hashmap.h"
+#include "hostname-util.h"
+#include "install-printf.h"
+#include "install.h"
#include "load-fragment.h"
+#include "macro.h"
+#include "rm-rf.h"
+#include "specifier.h"
+#include "string-util.h"
#include "strv.h"
-#include "fileio.h"
#include "test-helper.h"
-#include "hostname-util.h"
+#include "tests.h"
+#include "user-util.h"
+#include "util.h"
static int test_unit_file_get_set(void) {
int r;
@@ -47,15 +53,15 @@ static int test_unit_file_get_set(void) {
h = hashmap_new(&string_hash_ops);
assert_se(h);
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
if (r == -EPERM || r == -EACCES) {
- printf("Skipping test: unit_file_get_list: %s", strerror(-r));
+ log_notice_errno(r, "Skipping test: unit_file_get_list: %m");
return EXIT_TEST_SKIP;
}
- log_full(r == 0 ? LOG_INFO : LOG_ERR,
- "unit_file_get_list: %s", strerror(-r));
+ log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
+ "unit_file_get_list: %m");
if (r < 0)
return EXIT_FAILURE;
@@ -106,17 +112,30 @@ static void test_config_parse_exec(void) {
ExecCommand *c = NULL, *c1;
const char *ccc;
+ Manager *m = NULL;
+ Unit *u = NULL;
+
+ r = manager_new(UNIT_FILE_USER, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ log_notice_errno(r, "Skipping test: manager_new: %m");
+ return;
+ }
+
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ assert_se(u = unit_new(m, sizeof(Service)));
log_info("/* basic test */");
r = config_parse_exec(NULL, "fake", 1, "section", 1,
"LValue", 0, "/RValue r1",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
r = config_parse_exec(NULL, "fake", 2, "section", 1,
"LValue", 0, "/RValue///slashes r1///",
- &c, NULL);
+ &c, u);
log_info("/* test slashes */");
assert_se(r >= 0);
@@ -126,14 +145,14 @@ static void test_config_parse_exec(void) {
log_info("/* trailing slash */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/RValue/ argv0 r1",
- &c, NULL);
+ &c, u);
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",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
@@ -141,21 +160,21 @@ static void test_config_parse_exec(void) {
log_info("/* honour_argv0, no args */");
r = config_parse_exec(NULL, "fake", 3, "section", 1,
"LValue", 0, "@/RValue",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* no command, whitespace only, reset */");
r = config_parse_exec(NULL, "fake", 3, "section", 1,
"LValue", 0, " ",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c == NULL);
log_info("/* ignore && honour_argv0 */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "-@/RValue///slashes3 argv0a r1",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c;
check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
@@ -163,7 +182,7 @@ static void test_config_parse_exec(void) {
log_info("/* ignore && honour_argv0 */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "@-/RValue///slashes4 argv0b r1",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
@@ -171,14 +190,14 @@ static void test_config_parse_exec(void) {
log_info("/* ignore && ignore */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "--/RValue argv0 r1",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* ignore && ignore (2) */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "-@-/RValue argv0 r1",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
@@ -187,7 +206,7 @@ static void test_config_parse_exec(void) {
"LValue", 0,
"-@/RValue argv0 r1 ; "
"/goo/goo boo",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -200,7 +219,7 @@ static void test_config_parse_exec(void) {
"LValue", 0,
"-@/RValue argv0 r1 ; ; "
"/goo/goo boo",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -212,7 +231,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ; ",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -223,7 +242,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ;",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -234,7 +253,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"-@/RValue argv0 r1 ';'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
@@ -243,7 +262,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \\;",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -252,7 +271,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \\; /x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -262,7 +281,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \\;x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -272,7 +291,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \\073",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -281,7 +300,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/find \";\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -290,7 +309,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/sbin/find \";\" /x",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -300,7 +319,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon\" -1 -2",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -310,7 +329,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon -1 -2\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -320,7 +339,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -330,7 +349,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -340,7 +359,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1,
@@ -354,7 +373,7 @@ static void test_config_parse_exec(void) {
log_info("/* invalid character: \\%c */", *ccc);
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, path,
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
}
@@ -362,7 +381,7 @@ static void test_config_parse_exec(void) {
log_info("/* valid character: \\s */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/path\\s",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
@@ -371,7 +390,7 @@ static void test_config_parse_exec(void) {
r = config_parse_exec(NULL, "fake", 5, "section", 1,
"LValue", 0,
"/bin/grep '\\w+\\K'",
- &c, NULL);
+ &c, u);
assert_se(r >= 0);
c1 = c1->command_next;
check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
@@ -381,46 +400,49 @@ static void test_config_parse_exec(void) {
/* backslash is invalid */
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/path\\",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* missing ending ' */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/path 'foo",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* missing ending ' with trailing backslash */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "/path 'foo\\",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* invalid space between modifiers */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "- /path",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* only modifiers, no path */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "-",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c1->command_next == NULL);
log_info("/* empty argument, reset */");
r = config_parse_exec(NULL, "fake", 4, "section", 1,
"LValue", 0, "",
- &c, NULL);
+ &c, u);
assert_se(r == 0);
assert_se(c == NULL);
exec_command_free_list(c);
+
+ unit_free(u);
+ manager_free(m);
}
#define env_file_1 \
@@ -463,7 +485,7 @@ static void test_load_env_file_1(void) {
char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
@@ -486,7 +508,7 @@ static void test_load_env_file_2(void) {
char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
@@ -504,7 +526,7 @@ static void test_load_env_file_3(void) {
char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
@@ -520,7 +542,7 @@ static void test_load_env_file_4(void) {
_cleanup_close_ int fd;
int r;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
@@ -540,7 +562,7 @@ static void test_load_env_file_5(void) {
char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
@@ -554,86 +576,285 @@ static void test_load_env_file_5(void) {
static void test_install_printf(void) {
char name[] = "name.service",
- path[] = "/run/systemd/system/name.service",
- user[] = "xxxx-no-such-user";
- UnitFileInstallInfo i = {name, path, user};
- UnitFileInstallInfo i2 = {name, path, NULL};
+ path[] = "/run/systemd/system/name.service";
+ UnitFileInstallInfo i = { .name = name, .path = path, };
+ UnitFileInstallInfo i2 = { .name= name, .path = path, };
char name3[] = "name@inst.service",
path3[] = "/run/systemd/system/name.service";
- UnitFileInstallInfo i3 = {name3, path3, user};
- UnitFileInstallInfo i4 = {name3, path3, NULL};
+ UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
+ UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
- _cleanup_free_ char *mid, *bid, *host;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
assert_se((host = gethostname_malloc()));
+ assert_se((user = getusername_malloc()));
+ assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
#define expect(src, pattern, result) \
do { \
_cleanup_free_ char *t = NULL; \
_cleanup_free_ char \
*d1 = strdup(i.name), \
- *d2 = strdup(i.path), \
- *d3 = strdup(i.user); \
+ *d2 = strdup(i.path); \
assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
memzero(i.name, strlen(i.name)); \
memzero(i.path, strlen(i.path)); \
- memzero(i.user, strlen(i.user)); \
- assert_se(d1 && d2 && d3); \
+ assert_se(d1 && d2); \
if (result) { \
printf("%s\n", t); \
- assert_se(streq(t, result)); \
- } else assert_se(t == NULL); \
+ assert_se(streq(t, result)); \
+ } else assert_se(t == NULL); \
strcpy(i.name, d1); \
strcpy(i.path, d2); \
- strcpy(i.user, d3); \
- } while(false)
-
- assert_se(setenv("USER", "root", 1) == 0);
+ } while (false)
expect(i, "%n", "name.service");
expect(i, "%N", "name");
expect(i, "%p", "name");
expect(i, "%i", "");
- expect(i, "%u", "xxxx-no-such-user");
-
- DISABLE_WARNING_NONNULL;
- expect(i, "%U", NULL);
- REENABLE_WARNING;
+ expect(i, "%u", user);
+ expect(i, "%U", uid);
expect(i, "%m", mid);
expect(i, "%b", bid);
expect(i, "%H", host);
- expect(i2, "%u", "root");
- expect(i2, "%U", "0");
+ expect(i2, "%u", user);
+ expect(i2, "%U", uid);
expect(i3, "%n", "name@inst.service");
expect(i3, "%N", "name@inst");
expect(i3, "%p", "name");
- expect(i3, "%u", "xxxx-no-such-user");
-
- DISABLE_WARNING_NONNULL;
- expect(i3, "%U", NULL);
- REENABLE_WARNING;
+ expect(i3, "%u", user);
+ expect(i3, "%U", uid);
expect(i3, "%m", mid);
expect(i3, "%b", bid);
expect(i3, "%H", host);
- expect(i4, "%u", "root");
- expect(i4, "%U", "0");
+ expect(i4, "%u", user);
+ expect(i4, "%U", uid);
+}
+
+static uint64_t make_cap(int cap) {
+ return ((uint64_t) 1ULL << (uint64_t) cap);
+}
+
+static void test_config_parse_capability_set(void) {
+ /* int config_parse_capability_set(
+ const char *unit,
+ 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;
+ uint64_t capability_bounding_set = 0;
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_RAW",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == UINT64_C(0));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "~",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(cap_test_all(capability_bounding_set));
+
+ capability_bounding_set = 0;
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+}
+
+static void test_config_parse_rlimit(void) {
+ struct rlimit * rl[_RLIMIT_MAX] = {};
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ rl[RLIMIT_NOFILE]->rlim_cur = 10;
+ rl[RLIMIT_NOFILE]->rlim_max = 20;
+
+ /* Invalid values don't change rl */
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
+ assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
+}
+
+static void test_config_parse_pass_environ(void) {
+ /* int config_parse_pass_environ(
+ const char *unit,
+ 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;
+ _cleanup_strv_free_ char **passenv = NULL;
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "A B",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 2);
+ assert_se(streq(passenv[0], "A"));
+ assert_se(streq(passenv[1], "B"));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_isempty(passenv));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 1);
+ assert_se(streq(passenv[0], "normal_name"));
+
}
int main(int argc, char *argv[]) {
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r;
log_parse_environment();
log_open();
+ assert_se(runtime_dir = setup_fake_runtime_dir());
+
r = test_unit_file_get_set();
test_config_parse_exec();
+ test_config_parse_capability_set();
+ test_config_parse_rlimit();
+ test_config_parse_pass_environ();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index e5405fb7f3..2fd83f321c 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,21 +19,25 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <pwd.h>
+#include "alloc-util.h"
+#include "glob-util.h"
+#include "hostname-util.h"
+#include "macro.h"
#include "manager.h"
-#include "unit.h"
+#include "path-util.h"
+#include "specifier.h"
+#include "string-util.h"
+#include "test-helper.h"
#include "unit-name.h"
#include "unit-printf.h"
-#include "specifier.h"
+#include "unit.h"
+#include "user-util.h"
#include "util.h"
-#include "macro.h"
-#include "path-util.h"
-#include "test-helper.h"
-#include "hostname-util.h"
static void test_unit_name_is_valid(void) {
assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY));
@@ -63,26 +65,26 @@ static void test_unit_name_is_valid(void) {
assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY));
}
-static void test_u_n_r_i_one(const char *pattern, const char *repl, const char *expected, int ret) {
+static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) {
_cleanup_free_ char *t = NULL;
assert_se(unit_name_replace_instance(pattern, repl, &t) == ret);
puts(strna(t));
assert_se(streq_ptr(t, expected));
}
-static void test_u_n_r_i(void) {
+static void test_unit_name_replace_instance(void) {
puts("-------------------------------------------------");
- test_u_n_r_i_one("foo@.service", "waldo", "foo@waldo.service", 0);
- test_u_n_r_i_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
- test_u_n_r_i_one("xyz", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("foo.service", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one(".service", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("foo@", "waldo", NULL, -EINVAL);
- test_u_n_r_i_one("@bar", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0);
+ test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
+ test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one("", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one("foo.service", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one(".service", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one("foo@", "waldo", NULL, -EINVAL);
+ test_unit_name_replace_instance_one("@bar", "waldo", NULL, -EINVAL);
}
-static void test_u_n_f_p_one(const char *path, const char *suffix, const char *expected, int ret) {
+static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) {
_cleanup_free_ char *t = NULL;
assert_se(unit_name_from_path(path, suffix, &t) == ret);
@@ -97,19 +99,19 @@ static void test_u_n_f_p_one(const char *path, const char *suffix, const char *e
}
}
-static void test_u_n_f_p(void) {
+static void test_unit_name_from_path(void) {
puts("-------------------------------------------------");
- test_u_n_f_p_one("/waldo", ".mount", "waldo.mount", 0);
- test_u_n_f_p_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
- test_u_n_f_p_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
- test_u_n_f_p_one("", ".mount", "-.mount", 0);
- test_u_n_f_p_one("/", ".mount", "-.mount", 0);
- test_u_n_f_p_one("///", ".mount", "-.mount", 0);
- test_u_n_f_p_one("/foo/../bar", ".mount", NULL, -EINVAL);
- test_u_n_f_p_one("/foo/./bar", ".mount", NULL, -EINVAL);
+ test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0);
+ test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
+ test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
+ test_unit_name_from_path_one("", ".mount", "-.mount", 0);
+ test_unit_name_from_path_one("/", ".mount", "-.mount", 0);
+ test_unit_name_from_path_one("///", ".mount", "-.mount", 0);
+ test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL);
+ test_unit_name_from_path_one("/foo/./bar", ".mount", NULL, -EINVAL);
}
-static void test_u_n_f_p_i_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) {
+static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) {
_cleanup_free_ char *t = NULL;
assert_se(unit_name_from_path_instance(pattern, path, suffix, &t) == ret);
@@ -125,65 +127,71 @@ static void test_u_n_f_p_i_one(const char *pattern, const char *path, const char
}
}
-static void test_u_n_f_p_i(void) {
+static void test_unit_name_from_path_instance(void) {
puts("-------------------------------------------------");
- test_u_n_f_p_i_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
- test_u_n_f_p_i_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
- test_u_n_f_p_i_one("waldo", "/", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "///", ".mount", "waldo@-.mount", 0);
- test_u_n_f_p_i_one("waldo", "..", ".mount", NULL, -EINVAL);
- test_u_n_f_p_i_one("waldo", "/foo", ".waldi", NULL, -EINVAL);
- test_u_n_f_p_i_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "", ".mount", "waldo@-.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "///", ".mount", "waldo@-.mount", 0);
+ test_unit_name_from_path_instance_one("waldo", "..", ".mount", NULL, -EINVAL);
+ test_unit_name_from_path_instance_one("waldo", "/foo", ".waldi", NULL, -EINVAL);
+ test_unit_name_from_path_instance_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
}
-static void test_u_n_t_p_one(const char *unit, const char *path, int ret) {
+static void test_unit_name_to_path_one(const char *unit, const char *path, int ret) {
_cleanup_free_ char *p = NULL;
assert_se(unit_name_to_path(unit, &p) == ret);
assert_se(streq_ptr(path, p));
}
-static void test_u_n_t_p(void) {
- test_u_n_t_p_one("home.mount", "/home", 0);
- test_u_n_t_p_one("home-lennart.mount", "/home/lennart", 0);
- test_u_n_t_p_one("home-lennart-.mount", NULL, -EINVAL);
- test_u_n_t_p_one("-home-lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("-home--lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("home-..-lennart.mount", NULL, -EINVAL);
- test_u_n_t_p_one("", NULL, -EINVAL);
- test_u_n_t_p_one("home/foo", NULL, -EINVAL);
+static void test_unit_name_to_path(void) {
+ test_unit_name_to_path_one("home.mount", "/home", 0);
+ test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0);
+ test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL);
+ test_unit_name_to_path_one("-home-lennart.mount", NULL, -EINVAL);
+ test_unit_name_to_path_one("-home--lennart.mount", NULL, -EINVAL);
+ test_unit_name_to_path_one("home-..-lennart.mount", NULL, -EINVAL);
+ test_unit_name_to_path_one("", NULL, -EINVAL);
+ test_unit_name_to_path_one("home/foo", NULL, -EINVAL);
}
-static void test_u_n_m_one(const char *pattern, const char *expect, int ret) {
+static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pattern, const char *expect, int ret) {
_cleanup_free_ char *t = NULL;
- assert_se(unit_name_mangle(pattern, UNIT_NAME_NOGLOB, &t) == ret);
+ assert_se(unit_name_mangle(pattern, allow_globs, &t) == ret);
puts(strna(t));
assert_se(streq_ptr(t, expect));
if (t) {
_cleanup_free_ char *k = NULL;
- assert_se(unit_name_is_valid(t, UNIT_NAME_ANY));
+ assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) ||
+ (allow_globs == UNIT_NAME_GLOB && string_is_glob(t)));
- assert_se(unit_name_mangle(t, UNIT_NAME_NOGLOB, &k) == 0);
+ assert_se(unit_name_mangle(t, allow_globs, &k) == 0);
assert_se(streq_ptr(t, k));
}
}
-static void test_u_n_m(void) {
+static void test_unit_name_mangle(void) {
puts("-------------------------------------------------");
- test_u_n_m_one("foo.service", "foo.service", 0);
- test_u_n_m_one("/home", "home.mount", 1);
- test_u_n_m_one("/dev/sda", "dev-sda.device", 1);
- test_u_n_m_one("üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
- test_u_n_m_one("foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
- test_u_n_m_one("_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
- test_u_n_m_one("_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
- test_u_n_m_one("xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
- test_u_n_m_one("", NULL, -EINVAL);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foo.service", "foo.service", 0);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/home", "home.mount", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/dev/sda", "dev-sda.device", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
+ test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "", NULL, -EINVAL);
+
+ test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo.service", "foo.service", 0);
+ test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo", "foo.service", 1);
+ test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo*", "foo*", 0);
+ test_unit_name_mangle_one(UNIT_NAME_GLOB, "ü*", "\\xc3\\xbc*", 1);
}
static int test_unit_printf(void) {
@@ -191,17 +199,17 @@ static int test_unit_printf(void) {
Unit *u, *u2;
int r;
- _cleanup_free_ char *mid, *bid, *host, *root_uid;
- struct passwd *root;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
- assert_se((host = gethostname_malloc()));
-
- assert_se((root = getpwnam("root")));
- assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
+ assert_se(host = gethostname_malloc());
+ assert_se(user = getusername_malloc());
+ assert_se(asprintf(&uid, UID_FMT, getuid()));
+ assert_se(get_home_dir(&home) >= 0);
+ assert_se(get_shell(&shell) >= 0);
- r = manager_new(MANAGER_USER, true, &m);
+ r = manager_new(UNIT_FILE_USER, true, &m);
if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
@@ -220,8 +228,6 @@ static int test_unit_printf(void) {
assert_se(streq(t, expected)); \
}
- assert_se(setenv("USER", "root", 1) == 0);
- assert_se(setenv("HOME", "/root", 1) == 0);
assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
assert_se(u = unit_new(m, sizeof(Service)));
@@ -240,9 +246,9 @@ static int test_unit_printf(void) {
expect(u, "%p", "blah");
expect(u, "%P", "blah");
expect(u, "%i", "");
- expect(u, "%u", root->pw_name);
- expect(u, "%U", root_uid);
- expect(u, "%h", root->pw_dir);
+ expect(u, "%u", user);
+ expect(u, "%U", uid);
+ expect(u, "%h", home);
expect(u, "%m", mid);
expect(u, "%b", bid);
expect(u, "%H", host);
@@ -260,9 +266,9 @@ static int test_unit_printf(void) {
expect(u2, "%P", "blah");
expect(u2, "%i", "foo-foo");
expect(u2, "%I", "foo/foo");
- expect(u2, "%u", root->pw_name);
- expect(u2, "%U", root_uid);
- expect(u2, "%h", root->pw_dir);
+ expect(u2, "%u", user);
+ expect(u2, "%U", uid);
+ expect(u2, "%h", home);
expect(u2, "%m", mid);
expect(u2, "%b", bid);
expect(u2, "%H", host);
@@ -459,11 +465,11 @@ static void test_unit_name_path_unescape(void) {
int main(int argc, char* argv[]) {
int rc = 0;
test_unit_name_is_valid();
- test_u_n_r_i();
- test_u_n_f_p();
- test_u_n_f_p_i();
- test_u_n_m();
- test_u_n_t_p();
+ test_unit_name_replace_instance();
+ test_unit_name_from_path();
+ test_unit_name_from_path_instance();
+ test_unit_name_mangle();
+ test_unit_name_to_path();
TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
test_unit_instance_is_valid();
test_unit_prefix_is_valid();
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
new file mode 100644
index 0000000000..2a344a9f93
--- /dev/null
+++ b/src/test/test-user-util.c
@@ -0,0 +1,166 @@
+/***
+ 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 "alloc-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "user-util.h"
+#include "util.h"
+
+static void test_uid_to_name_one(uid_t uid, const char *name) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = uid_to_name(uid));
+ assert_se(streq_ptr(t, name));
+}
+
+static void test_gid_to_name_one(gid_t gid, const char *name) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = gid_to_name(gid));
+ assert_se(streq_ptr(t, name));
+}
+
+static void test_parse_uid(void) {
+ int r;
+ uid_t uid;
+
+ r = parse_uid("100", &uid);
+ assert_se(r == 0);
+ assert_se(uid == 100);
+
+ r = parse_uid("65535", &uid);
+ assert_se(r == -ENXIO);
+
+ r = parse_uid("asdsdas", &uid);
+ assert_se(r == -EINVAL);
+}
+
+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_valid_user_group_name(void) {
+ assert_se(!valid_user_group_name(NULL));
+ assert_se(!valid_user_group_name(""));
+ assert_se(!valid_user_group_name("1"));
+ assert_se(!valid_user_group_name("65535"));
+ assert_se(!valid_user_group_name("-1"));
+ assert_se(!valid_user_group_name("-kkk"));
+ assert_se(!valid_user_group_name("rööt"));
+ assert_se(!valid_user_group_name("."));
+ assert_se(!valid_user_group_name("eff.eff"));
+ assert_se(!valid_user_group_name("foo\nbar"));
+ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789"));
+ assert_se(!valid_user_group_name_or_id("aaa:bbb"));
+
+ assert_se(valid_user_group_name("root"));
+ assert_se(valid_user_group_name("lennart"));
+ assert_se(valid_user_group_name("LENNART"));
+ assert_se(valid_user_group_name("_kkk"));
+ assert_se(valid_user_group_name("kkk-"));
+ assert_se(valid_user_group_name("kk-k"));
+
+ assert_se(valid_user_group_name("some5"));
+ assert_se(!valid_user_group_name("5some"));
+ assert_se(valid_user_group_name("INNER5NUMBER"));
+}
+
+static void test_valid_user_group_name_or_id(void) {
+ assert_se(!valid_user_group_name_or_id(NULL));
+ assert_se(!valid_user_group_name_or_id(""));
+ assert_se(valid_user_group_name_or_id("0"));
+ assert_se(valid_user_group_name_or_id("1"));
+ assert_se(valid_user_group_name_or_id("65534"));
+ assert_se(!valid_user_group_name_or_id("65535"));
+ assert_se(valid_user_group_name_or_id("65536"));
+ assert_se(!valid_user_group_name_or_id("-1"));
+ assert_se(!valid_user_group_name_or_id("-kkk"));
+ assert_se(!valid_user_group_name_or_id("rööt"));
+ assert_se(!valid_user_group_name_or_id("."));
+ assert_se(!valid_user_group_name_or_id("eff.eff"));
+ assert_se(!valid_user_group_name_or_id("foo\nbar"));
+ assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789"));
+ assert_se(!valid_user_group_name_or_id("aaa:bbb"));
+
+ assert_se(valid_user_group_name_or_id("root"));
+ assert_se(valid_user_group_name_or_id("lennart"));
+ assert_se(valid_user_group_name_or_id("LENNART"));
+ assert_se(valid_user_group_name_or_id("_kkk"));
+ assert_se(valid_user_group_name_or_id("kkk-"));
+ assert_se(valid_user_group_name_or_id("kk-k"));
+
+ assert_se(valid_user_group_name_or_id("some5"));
+ assert_se(!valid_user_group_name_or_id("5some"));
+ assert_se(valid_user_group_name_or_id("INNER5NUMBER"));
+}
+
+static void test_valid_gecos(void) {
+
+ assert_se(!valid_gecos(NULL));
+ assert_se(valid_gecos(""));
+ assert_se(valid_gecos("test"));
+ assert_se(valid_gecos("Ümläüt"));
+ assert_se(!valid_gecos("In\nvalid"));
+ assert_se(!valid_gecos("In:valid"));
+}
+
+static void test_valid_home(void) {
+
+ assert_se(!valid_home(NULL));
+ assert_se(!valid_home(""));
+ assert_se(!valid_home("."));
+ assert_se(!valid_home("/home/.."));
+ assert_se(!valid_home("/home/../"));
+ assert_se(!valid_home("/home\n/foo"));
+ assert_se(!valid_home("./piep"));
+ assert_se(!valid_home("piep"));
+ assert_se(!valid_home("/home/user:lennart"));
+
+ assert_se(valid_home("/"));
+ assert_se(valid_home("/home"));
+ assert_se(valid_home("/home/foo"));
+}
+
+int main(int argc, char*argv[]) {
+
+ test_uid_to_name_one(0, "root");
+ test_uid_to_name_one(0xFFFF, "65535");
+ test_uid_to_name_one(0xFFFFFFFF, "4294967295");
+
+ test_gid_to_name_one(0, "root");
+ test_gid_to_name_one(TTY_GID, "tty");
+ test_gid_to_name_one(0xFFFF, "65535");
+ test_gid_to_name_one(0xFFFFFFFF, "4294967295");
+
+ test_parse_uid();
+ test_uid_ptr();
+
+ test_valid_user_group_name();
+ test_valid_user_group_name_or_id();
+ test_valid_gecos();
+ test_valid_home();
+
+ return 0;
+}
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index 346f8524c6..1ce5a5a24d 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,6 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "string-util.h"
#include "utf8.h"
#include "util.h"
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 7906c4d7bb..1b5cba86c1 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,31 +18,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <locale.h>
#include <errno.h>
-#include <signal.h>
-#include <math.h>
+#include <string.h>
#include <sys/wait.h>
+#include <unistd.h>
-#include "util.h"
-#include "mkdir.h"
-#include "rm-rf.h"
-#include "strv.h"
#include "def.h"
#include "fileio.h"
-#include "conf-parser.h"
-#include "virt.h"
-#include "process-util.h"
-#include "hostname-util.h"
-#include "signal-util.h"
-
-static void test_streq_ptr(void) {
- assert_se(streq_ptr(NULL, NULL));
- assert_se(!streq_ptr("abc", "cdef"));
-}
+#include "fs-util.h"
+#include "parse-util.h"
+#include "raw-clone.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "util.h"
static void test_align_power2(void) {
unsigned long i, p2;
@@ -136,19 +122,6 @@ static void test_container_of(void) {
v1) == &myval);
}
-static void test_alloca(void) {
- static const uint8_t zero[997] = { };
- char *t;
-
- t = alloca_align(17, 512);
- assert_se(!((uintptr_t)t & 0xff));
- memzero(t, 17);
-
- t = alloca0_align(997, 1024);
- assert_se(!((uintptr_t)t & 0x1ff));
- assert_se(!memcmp(t, zero, 997));
-}
-
static void test_div_round_up(void) {
int div;
@@ -182,723 +155,6 @@ static void test_div_round_up(void) {
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
}
-static void test_first_word(void) {
- assert_se(first_word("Hello", ""));
- assert_se(first_word("Hello", "Hello"));
- assert_se(first_word("Hello world", "Hello"));
- assert_se(first_word("Hello\tworld", "Hello"));
- assert_se(first_word("Hello\nworld", "Hello"));
- assert_se(first_word("Hello\rworld", "Hello"));
- assert_se(first_word("Hello ", "Hello"));
-
- assert_se(!first_word("Hello", "Hellooo"));
- assert_se(!first_word("Hello", "xxxxx"));
- assert_se(!first_word("Hellooo", "Hello"));
-}
-
-static void test_close_many(void) {
- int fds[3];
- char name0[] = "/tmp/test-close-many.XXXXXX";
- char name1[] = "/tmp/test-close-many.XXXXXX";
- char name2[] = "/tmp/test-close-many.XXXXXX";
-
- fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
- fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
- fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
-
- close_many(fds, 2);
-
- assert_se(fcntl(fds[0], F_GETFD) == -1);
- assert_se(fcntl(fds[1], F_GETFD) == -1);
- assert_se(fcntl(fds[2], F_GETFD) >= 0);
-
- safe_close(fds[2]);
-
- unlink(name0);
- unlink(name1);
- unlink(name2);
-}
-
-static void test_parse_boolean(void) {
- assert_se(parse_boolean("1") == 1);
- assert_se(parse_boolean("y") == 1);
- assert_se(parse_boolean("Y") == 1);
- assert_se(parse_boolean("yes") == 1);
- assert_se(parse_boolean("YES") == 1);
- assert_se(parse_boolean("true") == 1);
- assert_se(parse_boolean("TRUE") == 1);
- assert_se(parse_boolean("on") == 1);
- assert_se(parse_boolean("ON") == 1);
-
- assert_se(parse_boolean("0") == 0);
- assert_se(parse_boolean("n") == 0);
- assert_se(parse_boolean("N") == 0);
- assert_se(parse_boolean("no") == 0);
- assert_se(parse_boolean("NO") == 0);
- assert_se(parse_boolean("false") == 0);
- assert_se(parse_boolean("FALSE") == 0);
- assert_se(parse_boolean("off") == 0);
- assert_se(parse_boolean("OFF") == 0);
-
- assert_se(parse_boolean("garbage") < 0);
- assert_se(parse_boolean("") < 0);
- assert_se(parse_boolean("full") < 0);
-}
-
-static void test_parse_pid(void) {
- int r;
- pid_t pid;
-
- r = parse_pid("100", &pid);
- assert_se(r == 0);
- assert_se(pid == 100);
-
- r = parse_pid("0x7FFFFFFF", &pid);
- assert_se(r == 0);
- assert_se(pid == 2147483647);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("0", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("-100", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-}
-
-static void test_parse_uid(void) {
- int r;
- uid_t uid;
-
- r = parse_uid("100", &uid);
- assert_se(r == 0);
- assert_se(uid == 100);
-}
-
-static void test_safe_atolli(void) {
- int r;
- long long l;
-
- r = safe_atolli("12345", &l);
- assert_se(r == 0);
- assert_se(l == 12345);
-
- r = safe_atolli("junk", &l);
- assert_se(r == -EINVAL);
-}
-
-static void test_safe_atod(void) {
- int r;
- double d;
- char *e;
-
- r = safe_atod("junk", &d);
- assert_se(r == -EINVAL);
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- strtod("0,5", &e);
- assert_se(*e == ',');
-
- /* Check if this really is locale independent */
- if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
- }
-
- /* And check again, reset */
- assert_se(setlocale(LC_NUMERIC, "C"));
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- strtod("0,5", &e);
- assert_se(*e == ',');
-}
-
-static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
-
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
-
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
-
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
-
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
-}
-
-static void test_strstrip(void) {
- char *r;
- char input[] = " hello, waldo. ";
-
- r = strstrip(input);
- assert_se(streq(r, "hello, waldo."));
-}
-
-static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
-
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
-}
-
-static void test_in_charset(void) {
- assert_se(in_charset("dddaaabbbcccc", "abcd"));
- assert_se(!in_charset("dddaaabbbcccc", "abc f"));
-}
-
-static void test_hexchar(void) {
- assert_se(hexchar(0xa) == 'a');
- assert_se(hexchar(0x0) == '0');
-}
-
-static void test_unhexchar(void) {
- assert_se(unhexchar('a') == 0xA);
- assert_se(unhexchar('A') == 0xA);
- assert_se(unhexchar('0') == 0x0);
-}
-
-static void test_base32hexchar(void) {
- assert_se(base32hexchar(0) == '0');
- assert_se(base32hexchar(9) == '9');
- assert_se(base32hexchar(10) == 'A');
- assert_se(base32hexchar(31) == 'V');
-}
-
-static void test_unbase32hexchar(void) {
- assert_se(unbase32hexchar('0') == 0);
- assert_se(unbase32hexchar('9') == 9);
- assert_se(unbase32hexchar('A') == 10);
- assert_se(unbase32hexchar('V') == 31);
- assert_se(unbase32hexchar('=') == -EINVAL);
-}
-
-static void test_base64char(void) {
- assert_se(base64char(0) == 'A');
- assert_se(base64char(26) == 'a');
- assert_se(base64char(63) == '/');
-}
-
-static void test_unbase64char(void) {
- assert_se(unbase64char('A') == 0);
- assert_se(unbase64char('Z') == 25);
- assert_se(unbase64char('a') == 26);
- assert_se(unbase64char('z') == 51);
- assert_se(unbase64char('0') == 52);
- assert_se(unbase64char('9') == 61);
- assert_se(unbase64char('+') == 62);
- assert_se(unbase64char('/') == 63);
- assert_se(unbase64char('=') == -EINVAL);
-}
-
-static void test_octchar(void) {
- assert_se(octchar(00) == '0');
- assert_se(octchar(07) == '7');
-}
-
-static void test_unoctchar(void) {
- assert_se(unoctchar('0') == 00);
- assert_se(unoctchar('7') == 07);
-}
-
-static void test_decchar(void) {
- assert_se(decchar(0) == '0');
- assert_se(decchar(9) == '9');
-}
-
-static void test_undecchar(void) {
- assert_se(undecchar('0') == 0);
- assert_se(undecchar('9') == 9);
-}
-
-static void test_unhexmem(void) {
- const char *hex = "efa214921";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
- _cleanup_free_ void *mem = NULL;
- size_t len;
-
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
-
- assert_se((hex2 = hexmem(mem, len)));
-
- free(mem);
-
- assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
-
- free(hex2);
-
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base32hexmem(void) {
- char *b32;
-
- b32 = base32hexmem("", strlen(""), true);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), true);
- assert_se(b32);
- assert_se(streq(b32, "CO======"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNG===="));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU==="));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG="));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8======"));
- free(b32);
-
- b32 = base32hexmem("", strlen(""), false);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), false);
- assert_se(b32);
- assert_se(streq(b32, "CO"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNG"));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU"));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG"));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8"));
- free(b32);
-}
-
-static void test_unbase32hexmem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base64mem(void) {
- char *b64;
-
- b64 = base64mem("", strlen(""));
- assert_se(b64);
- assert_se(streq(b64, ""));
- free(b64);
-
- b64 = base64mem("f", strlen("f"));
- assert_se(b64);
- assert_se(streq(b64, "Zg=="));
- free(b64);
-
- b64 = base64mem("fo", strlen("fo"));
- assert_se(b64);
- assert_se(streq(b64, "Zm8="));
- free(b64);
-
- b64 = base64mem("foo", strlen("foo"));
- assert_se(b64);
- assert_se(streq(b64, "Zm9v"));
- free(b64);
-
- b64 = base64mem("foob", strlen("foob"));
- assert_se(b64);
- assert_se(streq(b64, "Zm9vYg=="));
- free(b64);
-
- b64 = base64mem("fooba", strlen("fooba"));
- assert_se(b64);
- assert_se(streq(b64, "Zm9vYmE="));
- free(b64);
-
- b64 = base64mem("foobar", strlen("foobar"));
- assert_se(b64);
- assert_se(streq(b64, "Zm9vYmFy"));
- free(b64);
-}
-
-static void test_unbase64mem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
-}
-
-static void test_cescape(void) {
- _cleanup_free_ char *escaped;
-
- assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
- assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
-}
-
-static void test_cunescape(void) {
- _cleanup_free_ char *unescaped;
-
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
- free(unescaped);
- unescaped = NULL;
-
- /* incomplete sequences */
- assert_se(cunescape("\\x0", 0, &unescaped) < 0);
- assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x0"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\x", 0, &unescaped) < 0);
- assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\", 0, &unescaped) < 0);
- assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\11", 0, &unescaped) < 0);
- assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\11"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\1", 0, &unescaped) < 0);
- assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\1"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
- assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "ßßΠA"));
- free(unescaped);
- unescaped = NULL;
-
- assert_se(cunescape("\\073", 0, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, ";"));
-}
-
-static void test_foreach_word(void) {
- const char *word, *state;
- size_t l;
- int i = 0;
- const char test[] = "test abc d\te f ";
- const char * const expected[] = {
- "test",
- "abc",
- "d",
- "e",
- "f",
- "",
- NULL
- };
-
- FOREACH_WORD(word, l, test, state)
- assert_se(strneq(expected[i++], word, l));
-}
-
-static void check(const char *test, char** expected, bool trailing) {
- const char *word, *state;
- size_t l;
- int i = 0;
-
- printf("<<<%s>>>\n", test);
- FOREACH_WORD_QUOTED(word, l, test, state) {
- _cleanup_free_ char *t = NULL;
-
- assert_se(t = strndup(word, l));
- assert_se(strneq(expected[i++], word, l));
- printf("<%s>\n", t);
- }
- 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_memdup_multiply(void) {
- int org[] = {1, 2, 3};
- int *dup;
-
- dup = (int*)memdup_multiply(org, sizeof(int), 3);
-
- assert_se(dup);
- assert_se(dup[0] == 1);
- assert_se(dup[1] == 2);
- assert_se(dup[2] == 3);
- free(dup);
-}
-
-static void test_hostname_is_valid(void) {
- assert_se(hostname_is_valid("foobar"));
- assert_se(hostname_is_valid("foobar.com"));
- assert_se(!hostname_is_valid("fööbar"));
- assert_se(!hostname_is_valid(""));
- assert_se(!hostname_is_valid("."));
- assert_se(!hostname_is_valid(".."));
- assert_se(!hostname_is_valid("foobar."));
- assert_se(!hostname_is_valid(".foobar"));
- assert_se(!hostname_is_valid("foo..bar"));
- assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
-}
-
-static void test_read_hostname_config(void) {
- char path[] = "/tmp/hostname.XXXXXX";
- char *hostname;
- int fd;
-
- fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC);
- assert(fd > 0);
- close(fd);
-
- /* simple hostname */
- write_string_file(path, "foo", WRITE_STRING_FILE_CREATE);
- assert_se(read_hostname_config(path, &hostname) == 0);
- assert_se(streq(hostname, "foo"));
- free(hostname);
- hostname = NULL;
-
- /* with comment */
- write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE);
- assert_se(read_hostname_config(path, &hostname) == 0);
- assert_se(hostname);
- assert_se(streq(hostname, "foo"));
- free(hostname);
- hostname = NULL;
-
- /* with comment and extra whitespace */
- write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE);
- assert_se(read_hostname_config(path, &hostname) == 0);
- assert_se(hostname);
- assert_se(streq(hostname, "foo"));
- free(hostname);
- hostname = NULL;
-
- /* cleans up name */
- write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE);
- assert_se(read_hostname_config(path, &hostname) == 0);
- assert_se(hostname);
- assert_se(streq(hostname, "foobar.com"));
- free(hostname);
- hostname = NULL;
-
- /* no value set */
- hostname = (char*) 0x1234;
- write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE);
- assert_se(read_hostname_config(path, &hostname) == -ENOENT);
- assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
-
- /* nonexisting file */
- assert_se(read_hostname_config("/non/existing", &hostname) == -ENOENT);
- assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
-
- unlink(path);
-}
-
static void test_u64log2(void) {
assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3);
@@ -918,163 +174,6 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
-static void test_parse_size(void) {
- off_t bytes;
-
- assert_se(parse_size("111", 1024, &bytes) == 0);
- assert_se(bytes == 111);
-
- assert_se(parse_size("111.4", 1024, &bytes) == 0);
- assert_se(bytes == 111);
-
- assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
- assert_se(bytes == 112);
-
- assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
- assert_se(bytes == 112);
-
- assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024 + 512);
-
- assert_se(parse_size("3. K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024);
-
- assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024);
-
- assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
- assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
-
- assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
- assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
-
- assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
- assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
-
- assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
- assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
-
- assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
- assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
-
- assert_se(parse_size("12P", 1024, &bytes) == 0);
- assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
-
- assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
- assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
-
- assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
- assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
- assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
-
- assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
-
- assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
-}
-
-static void test_config_parse_iec_off(void) {
- off_t offset = 0;
- assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
- assert_se(offset == 4 * 1024 * 1024);
-
- assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
-}
-
-static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
-}
-
-static void test_strrep(void) {
- _cleanup_free_ char *one, *three, *zero;
- one = strrep("waldo", 1);
- three = strrep("waldo", 3);
- zero = strrep("waldo", 0);
-
- assert_se(streq(one, "waldo"));
- assert_se(streq(three, "waldowaldowaldo"));
- assert_se(streq(zero, ""));
-}
-
-static void test_split_pair(void) {
- _cleanup_free_ char *a = NULL, *b = NULL;
-
- assert_se(split_pair("", "", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
- assert_se(split_pair("", "=", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
- assert_se(streq(a, "foo"));
- assert_se(streq(b, "bar"));
- free(a);
- free(b);
- assert_se(split_pair("==", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, ""));
- free(a);
- free(b);
-
- assert_se(split_pair("===", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, "="));
-}
-
-static void test_fstab_node_to_udev_node(void) {
- char *n;
-
- n = fstab_node_to_udev_node("LABEL=applé/jack");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
- free(n);
-
- n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PONIES=awesome");
- puts(n);
- assert_se(streq(n, "PONIES=awesome"));
- free(n);
-
- n = fstab_node_to_udev_node("/dev/xda1");
- puts(n);
- assert_se(streq(n, "/dev/xda1"));
- free(n);
-}
-
-static void test_get_files_in_directory(void) {
- _cleanup_strv_free_ char **l = NULL, **t = NULL;
-
- assert_se(get_files_in_directory("/tmp", &l) >= 0);
- assert_se(get_files_in_directory(".", &t) >= 0);
- assert_se(get_files_in_directory(".", NULL) >= 0);
-}
-
static void test_in_set(void) {
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
@@ -1085,50 +184,6 @@ static void test_in_set(void) {
assert_se(!IN_SET(0, 1, 2, 3, 4));
}
-static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
- _cleanup_free_ char *contents = NULL;
- size_t size;
- int fd, r;
- struct iovec iov[3];
-
- IOVEC_SET_STRING(iov[0], "abc\n");
- IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
- IOVEC_SET_STRING(iov[2], "");
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- printf("tmpfile: %s", name);
-
- r = writev(fd, iov, 3);
- assert_se(r >= 0);
-
- r = read_full_file(name, &contents, &size);
- assert_se(r == 0);
- printf("contents: %s", contents);
- assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
-}
-
-static void test_hexdump(void) {
- uint8_t data[146];
- unsigned i;
-
- hexdump(stdout, NULL, 0);
- hexdump(stdout, "", 0);
- hexdump(stdout, "", 1);
- hexdump(stdout, "x", 1);
- hexdump(stdout, "x", 2);
- hexdump(stdout, "foobar", 7);
- hexdump(stdout, "f\nobar", 7);
- hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
-
- for (i = 0; i < ELEMENTSOF(data); i++)
- data[i] = i*2;
-
- hexdump(stdout, data, sizeof(data));
-}
-
static void test_log2i(void) {
assert_se(log2i(1) == 0);
assert_se(log2i(2) == 1);
@@ -1140,331 +195,6 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
-static void test_foreach_string(void) {
- const char * const t[] = {
- "foo",
- "bar",
- "waldo",
- NULL
- };
- const char *x;
- unsigned i = 0;
-
- FOREACH_STRING(x, "foo", "bar", "waldo")
- assert_se(streq_ptr(t[i++], x));
-
- assert_se(i == 3);
-
- FOREACH_STRING(x, "zzz")
- assert_se(streq(x, "zzz"));
-}
-
-static void test_filename_is_valid(void) {
- char foo[FILENAME_MAX+2];
- int i;
-
- 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_valid(foo));
-
- assert_se(filename_is_valid("foo_bar-333"));
- assert_se(filename_is_valid("o.o"));
-}
-
-static void test_string_has_cc(void) {
- assert_se(string_has_cc("abc\1", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t\a"));
-
- assert_se(!string_has_cc("abc\t\t", "\t"));
- assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
- assert_se(!string_has_cc("a\ab\tc", "\t\a"));
-}
-
-static void test_ascii_strlower(void) {
- char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
- assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
-}
-
-static void test_files_same(void) {
- _cleanup_close_ int fd = -1;
- char name[] = "/tmp/test-files_same.XXXXXX";
- char name_alias[] = "/tmp/test-files_same.alias";
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_alias) >= 0);
-
- assert_se(files_same(name, name));
- assert_se(files_same(name, name_alias));
-
- unlink(name);
- unlink(name_alias);
-}
-
-static void test_is_valid_documentation_url(void) {
- 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(!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) {
- char *t;
-
- t = file_in_same_dir("/", "a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("/", "/a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("", "a");
- assert_se(streq(t, "a"));
- free(t);
-
- t = file_in_same_dir("a/", "a");
- assert_se(streq(t, "a/a"));
- free(t);
-
- t = file_in_same_dir("bar/foo", "bar");
- assert_se(streq(t, "bar/bar"));
- free(t);
-}
-
-static void test_endswith(void) {
- assert_se(endswith("foobar", "bar"));
- assert_se(endswith("foobar", ""));
- assert_se(endswith("foobar", "foobar"));
- assert_se(endswith("", ""));
-
- assert_se(!endswith("foobar", "foo"));
- assert_se(!endswith("foobar", "foobarfoofoo"));
-}
-
-static void test_close_nointr(void) {
- char name[] = "/tmp/test-test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
- assert_se(close_nointr(fd) < 0);
-
- unlink(name);
-}
-
-
-static void test_unlink_noerrno(void) {
- char name[] = "/tmp/test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
-
- {
- PROTECT_ERRNO;
- errno = -42;
- assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == -42);
- assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == -42);
- }
-}
-
-static void test_readlink_and_make_absolute(void) {
- char tempdir[] = "/tmp/test-readlink_and_make_absolute";
- char name[] = "/tmp/test-readlink_and_make_absolute/original";
- char name2[] = "test-readlink_and_make_absolute/original";
- char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
- char *r = NULL;
-
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
- assert_se(touch(name) >= 0);
-
- assert_se(symlink(name, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(chdir(tempdir) >= 0);
- assert_se(symlink(name2, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
-}
-
-static void test_ignore_signals(void) {
- assert_se(ignore_signals(SIGINT, -1) >= 0);
- assert_se(kill(getpid(), SIGINT) >= 0);
- assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
- assert_se(kill(getpid(), SIGUSR1) >= 0);
- assert_se(kill(getpid(), SIGUSR2) >= 0);
- assert_se(kill(getpid(), SIGTERM) >= 0);
- assert_se(kill(getpid(), SIGPIPE) >= 0);
- assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
-}
-
-static void test_strshorten(void) {
- char s[] = "foobar";
-
- assert_se(strlen(strshorten(s, 6)) == 6);
- assert_se(strlen(strshorten(s, 12)) == 6);
- assert_se(strlen(strshorten(s, 2)) == 2);
- assert_se(strlen(strshorten(s, 0)) == 0);
-}
-
-static void test_strjoina(void) {
- char *actual;
-
- actual = strjoina("", "foo", "bar");
- assert_se(streq(actual, "foobar"));
-
- actual = strjoina("foo", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- 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) {
- char name[] = "/tmp/test-is_symlink.XXXXXX";
- char name_link[] = "/tmp/test-is_symlink.link";
- _cleanup_close_ int fd = -1;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_link) >= 0);
-
- assert_se(is_symlink(name) == 0);
- assert_se(is_symlink(name_link) == 1);
- assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
-
- unlink(name);
- unlink(name_link);
-}
-
-static void test_search_and_fopen(void) {
- const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(basename(name), "r", "/", dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-
-static void test_search_and_fopen_nulstr(void) {
- const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-static void test_glob_exists(void) {
- char name[] = "/tmp/test-glob_exists.XXXXXX";
- int fd = -1;
- int r;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 1);
-
- r = unlink(name);
- assert_se(r == 0);
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 0);
-}
-
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";
@@ -1509,397 +239,6 @@ static void test_execute_directory(void) {
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
}
-static void test_unquote_first_word(void) {
- const char *p, *original;
- char *t;
-
- p = original = "foobar waldo";
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 7);
-
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(p == original + 12);
-
- assert_se(unquote_first_word(&p, &t, 0) == 0);
- assert_se(!t);
- assert_se(p == original + 12);
-
- p = original = "\"foobar\" \'waldo\'";
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 9);
-
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(p == original + 16);
-
- assert_se(unquote_first_word(&p, &t, 0) == 0);
- assert_se(!t);
- assert_se(p == original + 16);
-
- p = original = "\"";
- assert_se(unquote_first_word(&p, &t, 0) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'";
- assert_se(unquote_first_word(&p, &t, 0) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'fooo";
- assert_se(unquote_first_word(&p, &t, 0) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\'fooo";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "yay\'foo\'bar";
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "yayfoobar"));
- free(t);
- assert_se(p == original + 11);
-
- p = original = " foobar ";
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 12);
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) > 0);
- assert_se(streq(t, "foo\ba\x6ar"));
- free(t);
- assert_se(p == original + 13);
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(unquote_first_word(&p, &t, 0) > 0);
- assert_se(streq(t, "foobax6ar"));
- free(t);
- assert_se(p == original + 13);
-
- p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) > 0);
- assert_se(streq(t, "föo"));
- free(t);
- assert_se(p == original + 13);
-
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) > 0);
- assert_se(streq(t, "pi\360\237\222\251le"));
- free(t);
- assert_se(p == original + 32);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word(&p, &t, 0) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "foo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "foo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE_RELAX|UNQUOTE_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\ bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "\\w+@\\K[\\d.]+"));
- free(t);
- assert_se(p == original + 12);
-
- p = original = "\\w+\\b";
- assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "\\w+\b"));
- free(t);
- assert_se(p == original + 5);
-}
-
-static void test_unquote_first_word_and_warn(void) {
- const char *p, *original;
- char *t;
-
- p = original = "foobar waldo";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 7);
-
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(p == original + 12);
-
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == 0);
- assert_se(!t);
- assert_se(p == original + 12);
-
- p = original = "\"foobar\" \'waldo\'";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 9);
-
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(p == original + 16);
-
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == 0);
- assert_se(!t);
- assert_se(p == original + 16);
-
- p = original = "\"";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'fooo";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\'fooo";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo\ba\x6ar"));
- free(t);
- assert_se(p == original + 13);
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobax6ar"));
- free(t);
- assert_se(p == original + 13);
-
- p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "föo"));
- free(t);
- assert_se(p == original + 13);
-
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "pi\360\237\222\251le"));
- free(t);
- assert_se(p == original + 32);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE|UNQUOTE_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(p == original + 5);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word_and_warn(&p, &t, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\ bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "\\w+@\\K[\\d.]+"));
- free(t);
- assert_se(p == original + 12);
-
- p = original = "\\w+\\b";
- assert_se(unquote_first_word_and_warn(&p, &t, UNQUOTE_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "\\w+\b"));
- free(t);
- assert_se(p == original + 5);
-}
-
-static void test_unquote_many_words(void) {
- const char *p, *original;
- char *a, *b, *c;
-
- p = original = "foobar waldi piep";
- assert_se(unquote_many_words(&p, 0, &a, &b, &c, NULL) == 3);
- assert_se(p == original + 17);
- assert_se(streq_ptr(a, "foobar"));
- assert_se(streq_ptr(b, "waldi"));
- assert_se(streq_ptr(c, "piep"));
- free(a);
- free(b);
- free(c);
-
- p = original = "'foobar' wa\"ld\"i ";
- assert_se(unquote_many_words(&p, 0, &a, &b, &c, NULL) == 2);
- assert_se(p == original + 19);
- assert_se(streq_ptr(a, "foobar"));
- assert_se(streq_ptr(b, "waldi"));
- assert_se(streq_ptr(c, NULL));
- free(a);
- free(b);
-
- p = original = "";
- assert_se(unquote_many_words(&p, 0, &a, &b, &c, NULL) == 0);
- assert_se(p == original);
- assert_se(streq_ptr(a, NULL));
- assert_se(streq_ptr(b, NULL));
- assert_se(streq_ptr(c, NULL));
-
- p = original = " ";
- assert_se(unquote_many_words(&p, 0, &a, &b, &c, NULL) == 0);
- assert_se(p == original+2);
- assert_se(streq_ptr(a, NULL));
- assert_se(streq_ptr(b, NULL));
- assert_se(streq_ptr(c, NULL));
-
- p = original = "foobar";
- assert_se(unquote_many_words(&p, 0, NULL) == 0);
- assert_se(p == original);
-
- p = original = "foobar waldi";
- assert_se(unquote_many_words(&p, 0, &a, NULL) == 1);
- assert_se(p == original+7);
- assert_se(streq_ptr(a, "foobar"));
- free(a);
-
- p = original = " foobar ";
- assert_se(unquote_many_words(&p, 0, &a, NULL) == 1);
- assert_se(p == original+15);
- assert_se(streq_ptr(a, "foobar"));
- free(a);
-}
-
-static int parse_item(const char *key, const char *value) {
- assert_se(key);
-
- log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
- return 0;
-}
-
-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;
@@ -1907,7 +246,7 @@ static void test_raw_clone(void) {
log_info("before clone: getpid()→"PID_FMT, parent);
assert_se(raw_getpid() == parent);
- pid = raw_clone(0, NULL);
+ pid = raw_clone(0);
assert_se(pid >= 0);
pid2 = raw_getpid();
@@ -1925,239 +264,107 @@ static void test_raw_clone(void) {
}
}
-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_physical_memory(void) {
+ uint64_t p;
+ char buf[FORMAT_BYTES_MAX];
+
+ p = physical_memory();
+ assert_se(p > 0);
+ assert_se(p < UINT64_MAX);
+ assert_se(p % page_size() == 0);
+
+ log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p);
}
-static void test_uid_ptr(void) {
+static void test_physical_memory_scale(void) {
+ uint64_t p;
- assert_se(UID_TO_PTR(0) != NULL);
- assert_se(UID_TO_PTR(1000) != NULL);
+ p = physical_memory();
- assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
- assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
-}
+ assert_se(physical_memory_scale(0, 100) == 0);
+ assert_se(physical_memory_scale(100, 100) == p);
-static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
- char check[n];
+ log_info("Memory original: %" PRIu64, physical_memory());
+ log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100));
+ log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2);
+ log_info("Page size: %zu", page_size());
- 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);
+ /* There might be an uneven number of pages, hence permit these calculations to be half a page off... */
+ assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size());
+ assert_se(physical_memory_scale(200, 100) == p*2);
- assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
- assert_se(ftruncate(fd, n) >= 0);
+ assert_se(physical_memory_scale(0, 1) == 0);
+ assert_se(physical_memory_scale(1, 1) == p);
+ assert_se(physical_memory_scale(2, 1) == p*2);
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(read(fd, check, n) == (ssize_t) n);
+ assert_se(physical_memory_scale(0, 2) == 0);
- assert_se(memcmp(buffer, check, n) == 0);
-}
+ assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size());
+ assert_se(physical_memory_scale(2, 2) == p);
+ assert_se(physical_memory_scale(4, 2) == p*2);
-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));
+ assert_se(physical_memory_scale(0, UINT32_MAX) == 0);
+ assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p);
+
+ /* overflow */
+ assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
}
-static void test_shell_maybe_quote_one(const char *s, const char *expected) {
- _cleanup_free_ char *r;
+static void test_system_tasks_max(void) {
+ uint64_t t;
+
+ t = system_tasks_max();
+ assert_se(t > 0);
+ assert_se(t < UINT64_MAX);
- assert_se(r = shell_maybe_quote(s));
- assert_se(streq(r, expected));
+ log_info("Max tasks: %" PRIu64, t);
}
-static void test_shell_maybe_quote(void) {
+static void test_system_tasks_max_scale(void) {
+ uint64_t t;
- test_shell_maybe_quote_one("", "");
- test_shell_maybe_quote_one("\\", "\"\\\\\"");
- test_shell_maybe_quote_one("\"", "\"\\\"\"");
- test_shell_maybe_quote_one("foobar", "foobar");
- test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
-}
+ t = system_tasks_max();
-static void test_parse_mode(void) {
- mode_t m;
+ assert_se(system_tasks_max_scale(0, 100) == 0);
+ assert_se(system_tasks_max_scale(100, 100) == t);
- assert_se(parse_mode("-1", &m) < 0);
- assert_se(parse_mode("", &m) < 0);
- assert_se(parse_mode("888", &m) < 0);
- assert_se(parse_mode("77777", &m) < 0);
+ assert_se(system_tasks_max_scale(0, 1) == 0);
+ assert_se(system_tasks_max_scale(1, 1) == t);
+ assert_se(system_tasks_max_scale(2, 1) == 2*t);
- assert_se(parse_mode("544", &m) >= 0 && m == 0544);
- assert_se(parse_mode("777", &m) >= 0 && m == 0777);
- assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
- assert_se(parse_mode("0", &m) >= 0 && m == 0);
-}
+ assert_se(system_tasks_max_scale(0, 2) == 0);
+ assert_se(system_tasks_max_scale(1, 2) == t/2);
+ assert_se(system_tasks_max_scale(2, 2) == t);
+ assert_se(system_tasks_max_scale(3, 2) == (3*t)/2);
+ assert_se(system_tasks_max_scale(4, 2) == t*2);
+
+ assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0);
+ assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2);
+ assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t);
+
+ /* overflow */
-static void test_tempfn(void) {
- char *ret = NULL, *p;
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
+ assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
}
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_streq_ptr();
test_align_power2();
test_max();
test_container_of();
- test_alloca();
test_div_round_up();
- test_first_word();
- test_close_many();
- test_parse_boolean();
- test_parse_pid();
- test_parse_uid();
- test_safe_atolli();
- test_safe_atod();
- test_strappend();
- test_strstrip();
- test_delete_chars();
- test_in_charset();
- test_hexchar();
- test_unhexchar();
- test_base32hexchar();
- test_unbase32hexchar();
- test_base64char();
- test_unbase64char();
- test_octchar();
- test_unoctchar();
- test_decchar();
- test_undecchar();
- test_unhexmem();
- test_base32hexmem();
- test_unbase32hexmem();
- test_base64mem();
- test_unbase64mem();
- test_cescape();
- test_cunescape();
- test_foreach_word();
- test_foreach_word_quoted();
- test_memdup_multiply();
- test_hostname_is_valid();
- test_read_hostname_config();
test_u64log2();
test_protect_errno();
- test_parse_size();
- test_config_parse_iec_off();
- test_strextend();
- test_strrep();
- test_split_pair();
- test_fstab_node_to_udev_node();
- test_get_files_in_directory();
test_in_set();
- test_writing_tmpfile();
- test_hexdump();
test_log2i();
- test_foreach_string();
- test_filename_is_valid();
- test_string_has_cc();
- test_ascii_strlower();
- test_files_same();
- test_is_valid_documentation_url();
- test_file_in_same_dir();
- test_endswith();
- test_close_nointr();
- test_unlink_noerrno();
- test_readlink_and_make_absolute();
- test_ignore_signals();
- test_strshorten();
- test_strjoina();
- test_is_symlink();
- test_search_and_fopen();
- test_search_and_fopen_nulstr();
- test_glob_exists();
test_execute_directory();
- test_unquote_first_word();
- test_unquote_first_word_and_warn();
- test_unquote_many_words();
- test_parse_proc_cmdline();
test_raw_clone();
- test_same_fd();
- test_uid_ptr();
- test_sparse_write();
- test_shell_maybe_quote();
- test_parse_mode();
- test_tempfn();
+ test_physical_memory();
+ test_physical_memory_scale();
+ test_system_tasks_max();
+ test_system_tasks_max_scale();
return 0;
}
diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c
index 2e5d0c3aae..e3c19647fc 100644
--- a/src/test/test-watchdog.c
+++ b/src/test/test-watchdog.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,8 @@
#include <unistd.h>
-#include "watchdog.h"
#include "log.h"
+#include "watchdog.h"
int main(int argc, char *argv[]) {
usec_t t = 10 * USEC_PER_SEC;
diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c
new file mode 100644
index 0000000000..79a3a13af6
--- /dev/null
+++ b/src/test/test-web-util.c
@@ -0,0 +1,39 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "macro.h"
+#include "web-util.h"
+
+static void test_is_valid_documentation_url(void) {
+ 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(!documentation_url_is_valid("foo:"));
+ assert_se(!documentation_url_is_valid("info:"));
+ assert_se(!documentation_url_is_valid(""));
+}
+
+int main(int argc, char *argv[]) {
+ test_is_valid_documentation_url();
+
+ return 0;
+}
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
new file mode 100644
index 0000000000..267f29426c
--- /dev/null
+++ b/src/test/test-xattr-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "xattr-util.h"
+
+static void test_fgetxattrat_fake(void) {
+ char t[] = "/var/tmp/xattrtestXXXXXX";
+ _cleanup_close_ int fd = -1;
+ const char *x;
+ char v[3] = {};
+ int r;
+
+ assert_se(mkdtemp(t));
+ x = strjoina(t, "/test");
+ assert_se(touch(x) >= 0);
+
+ r = setxattr(x, "user.foo", "bar", 3, 0);
+ if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
+ goto cleanup;
+ assert_se(r >= 0);
+
+ fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+
+ assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
+ assert_se(memcmp(v, "bar", 3) == 0);
+
+ safe_close(fd);
+ fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+ assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
+
+cleanup:
+ assert_se(unlink(x) >= 0);
+ assert_se(rmdir(t) >= 0);
+}
+
+int main(void) {
+ test_fgetxattrat_fake();
+
+ return 0;
+}
diff --git a/src/test/test-xml.c b/src/test/test-xml.c
index ea109fbde0..b0b72fa78a 100644
--- a/src/test/test-xml.c
+++ b/src/test/test-xml.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,8 +19,10 @@
#include <stdarg.h>
-#include "xml.h"
+#include "alloc-util.h"
+#include "string-util.h"
#include "util.h"
+#include "xml.h"
static void test_one(const char *data, ...) {
void *state = NULL;