summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-03-26 16:35:12 +0100
committerAdrian Szyndela <adrian.s@samsung.com>2020-03-26 16:35:12 +0100
commit92c306c8e8329e9d68c52549d75e221fa08b61d9 (patch)
treea42d8a6284b6b6148b139de4be94fe23a3369033 /src/test
parentacdc1dd584c4c6cf32187adf95d43c4fe87b149f (diff)
parent1742aae2aa8cd33897250d6fcfbe10928e43eb2f (diff)
downloadsystemd-92c306c8e8329e9d68c52549d75e221fa08b61d9.tar.gz
systemd-92c306c8e8329e9d68c52549d75e221fa08b61d9.tar.bz2
systemd-92c306c8e8329e9d68c52549d75e221fa08b61d9.zip
Merge v240 into tizen
systemd 240
Diffstat (limited to 'src/test')
-rw-r--r--src/test/meson.build99
-rw-r--r--src/test/test-acl-util.c4
-rw-r--r--src/test/test-af-list.c6
-rw-r--r--src/test/test-architecture.c5
-rw-r--r--src/test/test-arphrd-list.c8
-rw-r--r--src/test/test-ask-password-api.c6
-rw-r--r--src/test/test-async.c4
-rw-r--r--src/test/test-barrier.c15
-rw-r--r--src/test/test-boot-timestamps.c38
-rw-r--r--src/test/test-bpf.c31
-rw-r--r--src/test/test-bus-util.c39
-rw-r--r--src/test/test-capability.c36
-rw-r--r--src/test/test-cgroup-mask.c105
-rw-r--r--src/test/test-cgroup-util.c18
-rw-r--r--src/test/test-cgroup.c2
-rw-r--r--src/test/test-chown-rec.c158
-rw-r--r--src/test/test-clock.c14
-rw-r--r--src/test/test-condition.c11
-rw-r--r--src/test/test-conf-files.c66
-rw-r--r--src/test/test-conf-parser.c35
-rw-r--r--src/test/test-copy.c4
-rw-r--r--src/test/test-daemon.c2
-rw-r--r--src/test/test-date.c5
-rw-r--r--src/test/test-dev-setup.c62
-rw-r--r--src/test/test-device-nodes.c3
-rw-r--r--src/test/test-dissect-image.c3
-rw-r--r--src/test/test-dns-domain.c182
-rw-r--r--src/test/test-emergency-action.c51
-rw-r--r--src/test/test-engine.c18
-rw-r--r--src/test/test-env-util.c76
-rw-r--r--src/test/test-escape.c5
-rw-r--r--src/test/test-exec-util.c49
-rw-r--r--src/test/test-execute.c189
-rw-r--r--src/test/test-fd-util.c5
-rw-r--r--src/test/test-fdset.c2
-rw-r--r--src/test/test-fileio.c220
-rw-r--r--src/test/test-firewall-util.c3
-rw-r--r--src/test/test-format-table.c28
-rw-r--r--src/test/test-fs-util.c213
-rw-r--r--src/test/test-glob-util.c2
-rw-r--r--src/test/test-hash.c9
-rw-r--r--src/test/test-hashmap-plain.c170
-rw-r--r--src/test/test-hashmap.c20
-rw-r--r--src/test/test-helper.c6
-rw-r--r--src/test/test-helper.h2
-rw-r--r--src/test/test-hexdecoct.c2
-rw-r--r--src/test/test-hostname-util.c9
-rw-r--r--src/test/test-id128.c2
-rw-r--r--src/test/test-in-addr-util.c82
-rw-r--r--src/test/test-install-root.c63
-rw-r--r--src/test/test-install.c4
-rw-r--r--src/test/test-ip-protocol-list.c64
-rw-r--r--src/test/test-ipcrm.c12
-rw-r--r--src/test/test-job-type.c2
-rw-r--r--src/test/test-journal-importer.c13
-rw-r--r--src/test/test-json.c462
-rw-r--r--src/test/test-libudev.c146
-rw-r--r--src/test/test-locale-util.c31
-rw-r--r--src/test/test-log.c26
-rw-r--r--src/test/test-loopback.c5
-rw-r--r--src/test/test-mount-util.c247
-rw-r--r--src/test/test-mountpoint-util.c268
-rw-r--r--src/test/test-namespace.c22
-rw-r--r--src/test/test-netlink-manual.c15
-rw-r--r--src/test/test-ns.c3
-rw-r--r--src/test/test-nscd-flush.c20
-rw-r--r--src/test/test-nss.c43
-rw-r--r--src/test/test-os-util.c5
-rw-r--r--src/test/test-parse-util.c2
-rw-r--r--src/test/test-path-lookup.c7
-rw-r--r--src/test/test-path-util.c130
-rw-r--r--src/test/test-path.c42
-rw-r--r--src/test/test-pretty-print.c40
-rw-r--r--src/test/test-prioq.c102
-rw-r--r--src/test/test-proc-cmdline.c136
-rw-r--r--src/test/test-process-util.c42
-rw-r--r--src/test/test-random-util.c39
-rw-r--r--src/test/test-rlimit-util.c1
-rw-r--r--src/test/test-sched-prio.c16
-rw-r--r--src/test/test-sd-hwdb.c74
-rw-r--r--src/test/test-seccomp.c205
-rw-r--r--src/test/test-selinux.c4
-rw-r--r--src/test/test-serialize.c208
-rw-r--r--src/test/test-set-disable-mempool.c53
-rw-r--r--src/test/test-set.c19
-rw-r--r--src/test/test-sigbus.c18
-rw-r--r--src/test/test-sleep.c53
-rw-r--r--src/test/test-socket-util.c412
-rw-r--r--src/test/test-specifier.c3
-rw-r--r--src/test/test-stat-util.c95
-rw-r--r--src/test/test-static-destruct.c34
-rw-r--r--src/test/test-string-util.c86
-rw-r--r--src/test/test-strip-tab-ansi.c1
-rw-r--r--src/test/test-strv.c238
-rwxr-xr-xsrc/test/test-systemd-tmpfiles.py19
-rw-r--r--src/test/test-tables.c6
-rw-r--r--src/test/test-terminal-util.c39
-rw-r--r--src/test/test-time-util.c74
-rw-r--r--src/test/test-tmpfiles.c5
-rw-r--r--src/test/test-udev.c121
-rw-r--r--src/test/test-umount.c22
-rw-r--r--src/test/test-unit-file.c53
-rw-r--r--src/test/test-unit-name.c24
-rw-r--r--src/test/test-user-util.c6
-rw-r--r--src/test/test-utf8.c47
-rw-r--r--src/test/test-util.c81
-rw-r--r--src/test/test-watch-pid.c21
-rw-r--r--src/test/test-watchdog.c8
-rw-r--r--src/test/test-xattr-util.c7
109 files changed, 4718 insertions, 1450 deletions
diff --git a/src/test/meson.build b/src/test/meson.build
index e2b69d44fa..50d001494e 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -6,7 +6,8 @@ test_hashmap_ordered_c = custom_target(
input : [awkscript, 'test-hashmap-plain.c'],
output : 'test-hashmap-ordered.c',
command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
- capture : true)
+ capture : true,
+ build_by_default : want_tests != 'false')
test_include_dir = include_directories('.')
@@ -26,14 +27,16 @@ test_libsystemd_sym_c = custom_target(
input : [libsystemd_sym_path] + systemd_headers,
output : 'test-libsystemd-sym.c',
command : [generate_sym_test_py, libsystemd_sym_path] + systemd_headers,
- capture : true)
+ capture : true,
+ build_by_default : want_tests != 'false')
test_libudev_sym_c = custom_target(
'test-libudev-sym.c',
input : [libudev_sym_path, libudev_h_path],
output : 'test-libudev-sym.c',
command : [generate_sym_test_py, '@INPUT0@', '@INPUT1@'],
- capture : true)
+ capture : true,
+ build_by_default : want_tests != 'false')
test_dlopen_c = files('test-dlopen.c')
@@ -60,6 +63,16 @@ tests += [
libmount,
libblkid]],
+ [['src/test/test-emergency-action.c'],
+ [libcore,
+ libshared],
+ []],
+
+ [['src/test/test-chown-rec.c'],
+ [libcore,
+ libshared],
+ []],
+
[['src/test/test-job-type.c'],
[libcore,
libshared],
@@ -81,6 +94,17 @@ tests += [
libblkid],
'', 'manual'],
+ [['src/test/test-nscd-flush.c'],
+ [libcore,
+ libshared],
+ [threads,
+ librt,
+ libseccomp,
+ libselinux,
+ libmount,
+ libblkid],
+ '', 'manual'],
+
[['src/test/test-loopback.c'],
[libcore,
libshared],
@@ -135,10 +159,18 @@ tests += [
libmount,
libblkid]],
+ [['src/test/test-serialize.c'],
+ [],
+ []],
+
[['src/test/test-utf8.c'],
[],
[]],
+ [['src/test/test-dev-setup.c'],
+ [],
+ []],
+
[['src/test/test-capability.c'],
[],
[libcap]],
@@ -156,6 +188,10 @@ tests += [
[],
[]],
+ [['src/test/test-static-destruct.c'],
+ [],
+ []],
+
[['src/test/test-sigbus.c'],
[],
[]],
@@ -188,10 +224,18 @@ tests += [
[],
[]],
+ [['src/test/test-json.c'],
+ [],
+ []],
+
[['src/test/test-mount-util.c'],
[],
[]],
+ [['src/test/test-mountpoint-util.c'],
+ [],
+ []],
+
[['src/test/test-exec-util.c'],
[],
[]],
@@ -284,6 +328,10 @@ tests += [
[],
[]],
+ [['src/test/test-pretty-print.c'],
+ [],
+ []],
+
[['src/test/test-uid-range.c'],
[],
[]],
@@ -392,6 +440,10 @@ tests += [
[],
[]],
+ [['src/test/test-set-disable-mempool.c'],
+ [],
+ [threads]],
+
[['src/test/test-bitmap.c'],
[],
[]],
@@ -609,6 +661,11 @@ tests += [
[],
[]],
+ [['src/test/test-ip-protocol-list.c',
+ shared_generated_gperf_headers],
+ [],
+ []],
+
[['src/test/test-journal-importer.c'],
[],
[]],
@@ -627,7 +684,7 @@ tests += [
libblkid,
libkmod,
libacl],
- '', 'manual'],
+ '', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'],
[['src/test/test-id128.c'],
[],
@@ -645,7 +702,7 @@ tests += [
[['src/test/test-nss.c'],
[],
[libdl],
- '', 'manual'],
+ 'ENABLE_NSS', 'manual'],
[['src/test/test-umount.c',
'src/core/mount-setup.c',
@@ -658,6 +715,10 @@ tests += [
[['src/test/test-bus-util.c'],
[],
[]],
+
+ [['src/test/test-sd-hwdb.c'],
+ [],
+ []],
]
############################################################
@@ -756,8 +817,7 @@ tests += [
libshared],
[threads,
libxz,
- liblz4],
- '', '', '-DCATALOG_DIR="@0@"'.format(build_catalog_dir)],
+ liblz4]],
[['src/journal/test-compress.c'],
[libjournal_core,
@@ -782,6 +842,10 @@ tests += [
############################################################
tests += [
+ [['src/libsystemd/sd-bus/test-bus-address.c'],
+ [],
+ [threads]],
+
[['src/libsystemd/sd-bus/test-bus-marshal.c'],
[],
[threads,
@@ -881,6 +945,27 @@ tests += [
[['src/libsystemd/sd-login/test-login.c'],
[],
[]],
+
+ [['src/libsystemd/sd-device/test-sd-device.c'],
+ [],
+ []],
+
+ [['src/libsystemd/sd-device/test-sd-device-thread.c'],
+ [libbasic,
+ libshared_static,
+ libsystemd],
+ [threads]],
+
+ [['src/libsystemd/sd-device/test-udev-device-thread.c'],
+ [libbasic,
+ libshared_static,
+ libudev],
+ [threads]],
+
+ [['src/libsystemd/sd-device/test-sd-device-monitor.c'],
+ [],
+ []],
+
]
if cxx.found()
diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c
index 81eb40444b..df879747f5 100644
--- a/src/test/test-acl-util.c
+++ b/src/test/test-acl-util.c
@@ -7,8 +7,8 @@
#include "acl-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "string-util.h"
+#include "tmpfile-util.h"
#include "user-util.h"
static void test_add_acls_for_user(void) {
@@ -32,7 +32,7 @@ static void test_add_acls_for_user(void) {
if (getuid() == 0) {
const char *nobody = NOBODY_USER_NAME;
- r = get_user_creds(&nobody, &uid, NULL, NULL, NULL);
+ r = get_user_creds(&nobody, &uid, NULL, NULL, NULL, 0);
if (r < 0)
uid = 0;
} else
diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c
index 8806744edb..c8ef3295b5 100644
--- a/src/test/test-af-list.c
+++ b/src/test/test-af-list.c
@@ -16,7 +16,7 @@ static const struct af_name* lookup_af(register const char *str, register GPERF_
int main(int argc, const char *argv[]) {
- unsigned int i;
+ unsigned i;
for (i = 0; i < ELEMENTSOF(af_names); i++) {
if (af_names[i]) {
@@ -27,8 +27,8 @@ int main(int argc, const char *argv[]) {
assert_se(af_to_name(af_max()) == NULL);
assert_se(af_to_name(-1) == NULL);
- assert_se(af_from_name("huddlduddl") == AF_UNSPEC);
- assert_se(af_from_name("") == AF_UNSPEC);
+ assert_se(af_from_name("huddlduddl") == -EINVAL);
+ assert_se(af_from_name("") == -EINVAL);
return 0;
}
diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c
index 6bc0a28a42..8c43bfc750 100644
--- a/src/test/test-architecture.c
+++ b/src/test/test-architecture.c
@@ -2,6 +2,7 @@
#include "architecture.h"
#include "log.h"
+#include "tests.h"
#include "util.h"
#include "virt.h"
@@ -9,6 +10,8 @@ int main(int argc, char *argv[]) {
int a, v;
const char *p;
+ test_setup_logging(LOG_INFO);
+
assert_se(architecture_from_string("") < 0);
assert_se(architecture_from_string(NULL) < 0);
assert_se(architecture_from_string("hoge") < 0);
@@ -18,7 +21,7 @@ int main(int argc, char *argv[]) {
v = detect_virtualization();
if (IN_SET(v, -EPERM, -EACCES))
- return EXIT_TEST_SKIP;
+ return log_tests_skipped("Cannot detect virtualization");
assert_se(v >= 0);
diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c
index 10cd9ebab9..3005fc1b69 100644
--- a/src/test/test-arphrd-list.c
+++ b/src/test/test-arphrd-list.c
@@ -4,8 +4,8 @@
#include <string.h>
#include "macro.h"
+#include "missing_network.h"
#include "string-util.h"
-#include "util.h"
_unused_ \
static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
@@ -16,7 +16,7 @@ static const struct arphrd_name* lookup_arphrd(register const char *str, registe
int main(int argc, const char *argv[]) {
- unsigned int i;
+ unsigned i;
for (i = 1; i < ELEMENTSOF(arphrd_names); i++) {
if (arphrd_names[i]) {
@@ -27,8 +27,8 @@ int main(int argc, const char *argv[]) {
assert_se(arphrd_to_name(arphrd_max()) == NULL);
assert_se(arphrd_to_name(0) == NULL);
- assert_se(arphrd_from_name("huddlduddl") == 0);
- assert_se(arphrd_from_name("") == 0);
+ assert_se(arphrd_from_name("huddlduddl") == -EINVAL);
+ assert_se(arphrd_from_name("") == -EINVAL);
return 0;
}
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
index ffd6da80fe..23b06be19b 100644
--- a/src/test/test-ask-password-api.c
+++ b/src/test/test-ask-password-api.c
@@ -3,15 +3,17 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "log.h"
+#include "strv.h"
static void ask_password(void) {
int r;
- _cleanup_free_ char *ret;
+ _cleanup_strv_free_ char **ret = NULL;
r = ask_password_tty(-1, "hello?", "da key", 0, 0, NULL, &ret);
assert(r >= 0);
+ assert(strv_length(ret) == 1);
- log_info("Got %s", ret);
+ log_info("Got %s", *ret);
}
int main(int argc, char **argv) {
diff --git a/src/test/test-async.c b/src/test/test-async.c
index 7c7dfe62da..4f5307889e 100644
--- a/src/test/test-async.c
+++ b/src/test/test-async.c
@@ -3,8 +3,8 @@
#include <unistd.h>
#include "async.h"
-#include "fileio.h"
#include "macro.h"
+#include "tmpfile-util.h"
#include "util.h"
static bool test_async = false;
@@ -32,7 +32,7 @@ int main(int argc, char *argv[]) {
assert_se(fcntl(fd, F_GETFD) == -1);
assert_se(test_async);
- unlink(name);
+ (void) unlink(name);
return 0;
}
diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c
index d2afd92f63..6ae84cd6fc 100644
--- a/src/test/test-barrier.c
+++ b/src/test/test-barrier.c
@@ -16,6 +16,7 @@
#include "barrier.h"
#include "util.h"
+#include "tests.h"
/* 20ms to test deadlocks; All timings use multiples of this constant as
* alarm/sleep timers. If this timeout is too small for slow machines to perform
@@ -419,18 +420,10 @@ TEST_BARRIER(test_barrier_pending_exit,
TEST_BARRIER_WAIT_SUCCESS(pid2));
int main(int argc, char *argv[]) {
- /*
- * This test uses real-time alarms and sleeps to test for CPU races
- * explicitly. This is highly fragile if your system is under load. We
- * already increased the BASE_TIME value to make the tests more robust,
- * but that just makes the test take significantly longer. Hence,
- * disable the test by default, so it will not break CI.
- */
- if (argc < 2)
- return EXIT_TEST_SKIP;
+ test_setup_logging(LOG_INFO);
- log_parse_environment();
- log_open();
+ if (!slow_tests_enabled())
+ return log_tests_skipped("slow tests are disabled");
test_barrier_sync();
test_barrier_wait_next();
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index ef39304b9f..a79e0cf16b 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -4,22 +4,19 @@
#include "boot-timestamps.h"
#include "efivars.h"
#include "log.h"
+#include "tests.h"
#include "util.h"
static int test_acpi_fpdt(void) {
- usec_t loader_start;
- usec_t loader_exit;
- char ts_start[FORMAT_TIMESPAN_MAX];
- char ts_exit[FORMAT_TIMESPAN_MAX];
- char ts_span[FORMAT_TIMESPAN_MAX];
+ char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX];
+ usec_t loader_start, loader_exit;
int r;
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
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");
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read ACPI FPDT: %m");
return ok ? 0 : r;
}
@@ -31,19 +28,15 @@ static int test_acpi_fpdt(void) {
}
static int test_efi_loader(void) {
- usec_t loader_start;
- usec_t loader_exit;
- char ts_start[FORMAT_TIMESPAN_MAX];
- char ts_exit[FORMAT_TIMESPAN_MAX];
- char ts_span[FORMAT_TIMESPAN_MAX];
+ char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX];
+ usec_t loader_start, loader_exit;
int r;
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP;
- log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
- r, "Failed to read EFI loader data: %m");
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read EFI loader data: %m");
return ok ? 0 : r;
}
@@ -56,17 +49,16 @@ static int test_efi_loader(void) {
static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
- int r;
dual_timestamp fw, l, k;
+ int r;
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
- bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP;
- log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
- r, "Failed to read variables: %m");
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read variables: %m");
return ok ? 0 : r;
}
@@ -81,8 +73,7 @@ static int test_boot_timestamps(void) {
int main(int argc, char* argv[]) {
int p, q, r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
p = test_acpi_fpdt();
assert(p >= 0);
@@ -91,5 +82,8 @@ int main(int argc, char* argv[]) {
r = test_boot_timestamps();
assert(r >= 0);
- return (p > 0 || q > 0 || r >> 0) ? EXIT_SUCCESS : EXIT_TEST_SKIP;
+ if (p == 0 && q == 0 && r == 0)
+ return log_tests_skipped("access to firmware variables not possible");
+
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c
index 4d89bd46d3..ea5f0f5bc6 100644
--- a/src/test/test-bpf.c
+++ b/src/test/test-bpf.c
@@ -28,17 +28,13 @@ int main(int argc, char *argv[]) {
char log_buf[65535];
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice("cgroupfs not available, skipping tests");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
- assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(set_unit_path(get_testdata_dir()) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &p);
@@ -47,16 +43,12 @@ int main(int argc, char *argv[]) {
r = bpf_program_add_instructions(p, exit_insn, ELEMENTSOF(exit_insn));
assert(r == 0);
- if (getuid() != 0) {
- log_notice("Not running as root, skipping kernel related tests.");
- return EXIT_TEST_SKIP;
- }
+ if (getuid() != 0)
+ return log_tests_skipped("not running as root");
r = bpf_firewall_supported();
- if (r == BPF_FIREWALL_UNSUPPORTED) {
- log_notice("BPF firewalling not supported, skipping");
- return EXIT_TEST_SKIP;
- }
+ if (r == BPF_FIREWALL_UNSUPPORTED)
+ return log_tests_skipped("BPF firewalling not supported");
assert_se(r > 0);
if (r == BPF_FIREWALL_SUPPORTED_WITH_MULTI)
@@ -71,7 +63,7 @@ int main(int argc, char *argv[]) {
/* The simple tests suceeded. Now let's try full unit-based use-case. */
- assert_se(manager_new(UNIT_FILE_USER, true, &m) >= 0);
+ assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
assert_se(u = unit_new(m, sizeof(Service)));
@@ -110,9 +102,8 @@ int main(int argc, char *argv[]) {
unit_dump(u, stdout, NULL);
r = bpf_firewall_compile(u);
- if (IN_SET(r, -ENOTTY, -ENOSYS, -EPERM ))
- /* Kernel doesn't support the necessary bpf bits, or masked out via seccomp? */
- return EXIT_TEST_SKIP;
+ if (IN_SET(r, -ENOTTY, -ENOSYS, -EPERM))
+ return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)");
assert_se(r >= 0);
assert(u->ip_bpf_ingress);
diff --git a/src/test/test-bus-util.c b/src/test/test-bus-util.c
index 791b3928fe..a536608ce0 100644
--- a/src/test/test-bus-util.c
+++ b/src/test/test-bus-util.c
@@ -2,38 +2,7 @@
#include "bus-util.h"
#include "log.h"
-
-static void test_name_async(unsigned n_messages) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int r;
- unsigned i;
-
- log_info("/* %s (%u) */", __func__, n_messages);
-
- r = bus_open_system_watch_bind_with_description(&bus, "test-bus");
- if (r < 0) {
- log_error_errno(r, "Failed to connect to bus: %m");
- return;
- }
-
- r = bus_request_name_async_may_reload_dbus(bus, NULL, "org.freedesktop.systemd.test-bus-util", 0, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to request name: %m");
- return;
- }
-
- for (i = 0; i < n_messages; i++) {
- r = sd_bus_process(bus, NULL);
- log_debug("stage %u: sd_bus_process returned %d", i, r);
- if (r < 0) {
- log_notice_errno(r, "Processing failed: %m");
- return;
- }
-
- if (r > 0 && i + 1 < n_messages)
- (void) sd_bus_wait(bus, USEC_PER_SEC / 3);
- }
-}
+#include "tests.h"
static int callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
return 1;
@@ -78,12 +47,8 @@ static void test_destroy_callback(void) {
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
- test_name_async(0);
- test_name_async(20);
test_destroy_callback();
return 0;
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index af6d808b6d..dae85f2f91 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -14,13 +14,19 @@
#include "fileio.h"
#include "macro.h"
#include "parse-util.h"
+#include "tests.h"
#include "util.h"
static uid_t test_uid = -1;
static gid_t test_gid = -1;
+#if HAS_FEATURE_ADDRESS_SANITIZER
+/* Keep CAP_SYS_PTRACE when running under Address Sanitizer */
+static const uint64_t test_flags = UINT64_C(1) << CAP_SYS_PTRACE;
+#else
/* We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage */
-static uint64_t test_flags = 1ULL << CAP_DAC_OVERRIDE;
+static const uint64_t test_flags = UINT64_C(1) << CAP_DAC_OVERRIDE;
+#endif
/* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */
static void test_last_cap_file(void) {
@@ -91,10 +97,9 @@ static int setup_tests(bool *run_ambient) {
int r;
nobody = getpwnam(NOBODY_USER_NAME);
- if (!nobody) {
- log_error_errno(errno, "Could not find nobody user: %m");
- return -EXIT_TEST_SKIP;
- }
+ if (!nobody)
+ return log_error_errno(errno, "Could not find nobody user: %m");
+
test_uid = nobody->pw_uid;
test_gid = nobody->pw_gid;
@@ -180,8 +185,6 @@ static void test_update_inherited_set(void) {
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);
@@ -197,12 +200,6 @@ static void test_set_ambient_caps(void) {
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);
@@ -218,23 +215,20 @@ static void test_set_ambient_caps(void) {
}
int main(int argc, char *argv[]) {
- int r;
bool run_ambient;
+ test_setup_logging(LOG_INFO);
+
test_last_cap_file();
test_last_cap_probe();
- log_parse_environment();
- log_open();
-
log_info("have ambient caps: %s", yes_no(ambient_capabilities_supported()));
if (getuid() != 0)
- return EXIT_TEST_SKIP;
+ return log_tests_skipped("not running as root");
- r = setup_tests(&run_ambient);
- if (r < 0)
- return -r;
+ if (setup_tests(&run_ambient) < 0)
+ return log_tests_skipped("setup failed");
show_capabilities();
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index d65959edf1..7f6c0c2772 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -1,10 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 David Strauss
-***/
#include <stdio.h>
+#include "cgroup.h"
+#include "cgroup-util.h"
#include "macro.h"
#include "manager.h"
#include "rm-rf.h"
@@ -13,26 +12,41 @@
#include "tests.h"
#include "unit.h"
+#define ASSERT_CGROUP_MASK(got, expected) \
+ log_cgroup_mask(got, expected); \
+ assert_se(got == expected)
+
+#define ASSERT_CGROUP_MASK_JOINED(got, expected) ASSERT_CGROUP_MASK(got, CGROUP_MASK_EXTEND_JOINED(expected))
+
+static void log_cgroup_mask(CGroupMask got, CGroupMask expected) {
+ _cleanup_free_ char *e_store = NULL, *g_store = NULL;
+
+ assert_se(cg_mask_to_string(expected, &e_store) >= 0);
+ log_info("Expected mask: %s\n", e_store);
+ assert_se(cg_mask_to_string(got, &g_store) >= 0);
+ log_info("Got mask: %s\n", g_store);
+}
+
static int test_cgroup_mask(void) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
- Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep;
+ Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf;
int r;
+ CGroupMask cpu_accounting_mask = get_cpu_accounting_mask();
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- puts("Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
/* Prepare the manager. */
- assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(set_unit_path(get_testdata_dir()) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
if (IN_SET(r, -EPERM, -EACCES)) {
- puts("manager_new: Permission denied. Skipping test.");
- return EXIT_TEST_SKIP;
+ log_error_errno(r, "manager_new: %m");
+ return log_tests_skipped("cannot create manager");
}
+
assert_se(r >= 0);
/* Turn off all kinds of default accouning, so that we can
@@ -54,43 +68,55 @@ static int test_cgroup_mask(void) {
assert_se(manager_load_startable_unit_or_warn(m, "daughter.service", NULL, &daughter) >= 0);
assert_se(manager_load_startable_unit_or_warn(m, "grandchild.service", NULL, &grandchild) >= 0);
assert_se(manager_load_startable_unit_or_warn(m, "parent-deep.slice", NULL, &parent_deep) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "nomem.slice", NULL, &nomem_parent) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "nomemleaf.service", NULL, &nomem_leaf) >= 0);
assert_se(UNIT_DEREF(son->slice) == parent);
assert_se(UNIT_DEREF(daughter->slice) == parent);
assert_se(UNIT_DEREF(parent_deep->slice) == parent);
assert_se(UNIT_DEREF(grandchild->slice) == parent_deep);
+ assert_se(UNIT_DEREF(nomem_leaf->slice) == nomem_parent);
root = UNIT_DEREF(parent->slice);
+ assert_se(UNIT_DEREF(nomem_parent->slice) == root);
/* Verify per-unit cgroups settings. */
- 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);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(son), CGROUP_MASK_CPU);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(daughter), cpu_accounting_mask);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(grandchild), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_parent), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
+ ASSERT_CGROUP_MASK_JOINED(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_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));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(son), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(daughter), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(grandchild), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent_deep), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_leaf), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of sibling masks. */
- 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_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));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(grandchild), 0);
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of target masks. */
- 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_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));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(son), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild), 0);
+ ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
+ ASSERT_CGROUP_MASK(unit_get_target_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
return 0;
}
@@ -104,7 +130,7 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) {
static void test_cg_mask_to_string(void) {
test_cg_mask_to_string_one(0, NULL);
- test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct io blkio memory devices pids");
+ test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct io blkio memory devices pids bpf-firewall bpf-devices");
test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu");
test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct");
test_cg_mask_to_string_one(CGROUP_MASK_IO, "io");
@@ -120,13 +146,12 @@ static void test_cg_mask_to_string(void) {
}
int main(int argc, char* argv[]) {
- int rc = 0;
+ int rc = EXIT_SUCCESS;
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
- TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask());
test_cg_mask_to_string();
+ 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 d49356315e..a3239d73f5 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -14,6 +14,7 @@
#include "string-util.h"
#include "strv.h"
#include "test-helper.h"
+#include "tests.h"
#include "user-util.h"
#include "util.h"
@@ -296,7 +297,7 @@ static void test_shift_path(void) {
test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo");
test_shift_path_one("/foobar/waldo", "", "/foobar/waldo");
test_shift_path_one("/foobar/waldo", "/foobar", "/waldo");
- test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo");
+ test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo");
}
static void test_mask_supported(void) {
@@ -368,6 +369,17 @@ static void test_is_wanted(void) {
"systemd.unified_cgroup_hierarchy=0 "
"systemd.legacy_systemd_cgroup_controller=0", 1) >= 0);
test_is_wanted_print(false);
+
+ /* cgroup_no_v1=all implies unified cgroup hierarchy, unless otherwise
+ * explicitly specified. */
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "cgroup_no_v1=all", 1) >= 0);
+ test_is_wanted_print(false);
+
+ assert_se(setenv("SYSTEMD_PROC_CMDLINE",
+ "cgroup_no_v1=all "
+ "systemd.unified_cgroup_hierarchy=0", 1) >= 0);
+ test_is_wanted_print(false);
}
static void test_cg_tests(void) {
@@ -447,9 +459,7 @@ static void test_cg_get_keyed_attribute(void) {
}
int main(void) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_path_decode_unit();
test_path_get_unit();
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 9211c996ac..5cdfd2dc54 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -9,7 +9,7 @@
#include "string-util.h"
#include "util.h"
-int main(int argc, char*argv[]) {
+int main(int argc, char *argv[]) {
char *path;
char *c, *p;
diff --git a/src/test/test-chown-rec.c b/src/test/test-chown-rec.c
new file mode 100644
index 0000000000..305d44f568
--- /dev/null
+++ b/src/test/test-chown-rec.c
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/xattr.h>
+
+#include "alloc-util.h"
+#include "chown-recursive.h"
+#include "log.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
+
+static const uint8_t acl[] = {
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x07, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+static const uint8_t default_acl[] = {
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x07, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+static bool has_xattr(const char *p) {
+ char buffer[sizeof(acl) * 4];
+
+ if (lgetxattr(p, "system.posix_acl_access", buffer, sizeof(buffer)) < 0) {
+ if (IN_SET(errno, EOPNOTSUPP, ENOTTY, ENODATA, ENOSYS))
+ return false;
+ }
+
+ return true;
+}
+
+static void test_chown_recursive(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+ struct stat st;
+ const char *p;
+
+ umask(022);
+ assert_se(mkdtemp_malloc(NULL, &t) >= 0);
+
+ p = strjoina(t, "/dir");
+ assert_se(mkdir(p, 0777) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/symlink");
+ assert_se(symlink("../../", p) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISLNK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0777);
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/reg");
+ assert_se(mknod(p, S_IFREG|0777, 0) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/sock");
+ assert_se(mknod(p, S_IFSOCK|0777, 0) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISSOCK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/fifo");
+ assert_se(mknod(p, S_IFIFO|0777, 0) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISFIFO(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(!has_xattr(p));
+
+ /* We now apply an xattr to the dir, and check it again */
+ p = strjoina(t, "/dir");
+ assert_se(setxattr(p, "system.posix_acl_access", acl, sizeof(acl), 0) >= 0);
+ assert_se(setxattr(p, "system.posix_acl_default", default_acl, sizeof(default_acl), 0) >= 0);
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */
+ assert_se(st.st_uid == 0);
+ assert_se(st.st_gid == 0);
+ assert_se(has_xattr(p));
+
+ assert_se(path_chown_recursive(t, 1, 2) >= 0);
+
+ p = strjoina(t, "/dir");
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0775);
+ assert_se(st.st_uid == 1);
+ assert_se(st.st_gid == 2);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/symlink");
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISLNK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0777);
+ assert_se(st.st_uid == 1);
+ assert_se(st.st_gid == 2);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/reg");
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 1);
+ assert_se(st.st_gid == 2);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/sock");
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISSOCK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 1);
+ assert_se(st.st_gid == 2);
+ assert_se(!has_xattr(p));
+
+ p = strjoina(t, "/dir/fifo");
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISFIFO(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0755);
+ assert_se(st.st_uid == 1);
+ assert_se(st.st_gid == 2);
+ assert_se(!has_xattr(p));
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ if (geteuid() != 0)
+ return log_tests_skipped("not running as root");
+
+ test_chown_recursive();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-clock.c b/src/test/test-clock.c
index 50e9b7756f..018e679b45 100644
--- a/src/test/test-clock.c
+++ b/src/test/test-clock.c
@@ -9,12 +9,13 @@
#include "clock-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "tmpfile-util.h"
static void test_clock_is_localtime(void) {
- char adjtime[] = "/tmp/test-adjtime.XXXXXX";
- int fd = -1;
+ _cleanup_(unlink_tempfilep) char adjtime[] = "/tmp/test-adjtime.XXXXXX";
_cleanup_fclose_ FILE* f = NULL;
static const struct scenario {
@@ -41,22 +42,17 @@ static void test_clock_is_localtime(void) {
/* without an adjtime file we default to UTC */
assert_se(clock_is_localtime("/nonexisting/adjtime") == 0);
- fd = mkostemp_safe(adjtime);
- assert_se(fd >= 0);
+ assert_se(fmkostemp_safe(adjtime, "w", &f) == 0);
log_info("adjtime test file: %s", adjtime);
- f = fdopen(fd, "w");
- assert_se(f);
for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) {
log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result);
log_info("%s", scenarios[i].contents);
rewind(f);
- ftruncate(fd, 0);
+ ftruncate(fileno(f), 0);
assert_se(write_string_stream(f, scenarios[i].contents, WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result);
}
-
- unlink(adjtime);
}
/* Test with the real /etc/adjtime */
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 7ce6ee80ea..5c2d00af88 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -26,6 +26,7 @@
#include "strv.h"
#include "tomoyo-util.h"
#include "user-util.h"
+#include "tests.h"
#include "util.h"
#include "virt.h"
@@ -113,7 +114,7 @@ static void test_condition_test_path(void) {
condition_free(condition);
}
-static int test_condition_test_control_group_controller(void) {
+static void test_condition_test_control_group_controller(void) {
Condition *condition;
CGroupMask system_mask;
CGroupController controller;
@@ -123,7 +124,7 @@ static int test_condition_test_control_group_controller(void) {
r = cg_unified_flush();
if (r < 0) {
log_notice_errno(r, "Skipping ConditionControlGroupController tests: %m");
- return EXIT_TEST_SKIP;
+ return;
}
/* Invalid controllers are ignored */
@@ -180,8 +181,6 @@ static int test_condition_test_control_group_controller(void) {
assert_se(condition);
assert_se(!condition_test(condition));
condition_free(condition);
-
- return EXIT_SUCCESS;
}
static void test_condition_test_ac_power(void) {
@@ -675,9 +674,7 @@ static void test_condition_test_group(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_condition_test_path();
test_condition_test_ac_power();
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 2ec2dfc261..9fd8b6b590 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -13,9 +13,11 @@
#include "macro.h"
#include "mkdir.h"
#include "parse-util.h"
+#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
#include "user-util.h"
#include "util.h"
@@ -42,7 +44,7 @@ static void test_conf_files_list(bool use_root) {
_cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL;
const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c, *mask;
- log_debug("/* %s */", __func__);
+ log_debug("/* %s(%s) */", __func__, yes_no(use_root));
setup_test_dir(tmp_dir,
"/dir1/a.conf",
@@ -92,12 +94,68 @@ static void test_conf_files_list(bool use_root) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
+static void test_conf_files_insert(const char *root) {
+ _cleanup_strv_free_ char **s = NULL;
+
+ log_info("/* %s root=%s */", __func__, strempty(root));
+
+ char **dirs = STRV_MAKE("/dir1", "/dir2", "/dir3");
+
+ _cleanup_free_ const char
+ *foo1 = prefix_root(root, "/dir1/foo.conf"),
+ *foo2 = prefix_root(root, "/dir2/foo.conf"),
+ *bar2 = prefix_root(root, "/dir2/bar.conf"),
+ *zzz3 = prefix_root(root, "/dir3/zzz.conf"),
+ *whatever = prefix_root(root, "/whatever.conf");
+
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
+
+ /* The same file again, https://github.com/systemd/systemd/issues/11124 */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
+
+ /* Lower priority → new entry is ignored */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/foo.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
+
+ /* Higher priority → new entry replaces */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir1/foo.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(foo1)));
+
+ /* Earlier basename */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1)));
+
+ /* Later basename */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
+
+ /* All lower priority → all ignored */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0);
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0);
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/bar.conf") == 0);
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
+
+ /* Two entries that don't match any of the directories, but match basename */
+ assert_se(conf_files_insert(&s, root, dirs, "/dir4/zzz.conf") == 0);
+ assert_se(conf_files_insert(&s, root, dirs, "/zzz.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
+
+ /* An entry that doesn't match any of the directories, no match at all */
+ assert_se(conf_files_insert(&s, root, dirs, "/whatever.conf") == 0);
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, whatever, zzz3)));
+}
+
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_conf_files_list(false);
test_conf_files_list(true);
+ test_conf_files_insert(NULL);
+ test_conf_files_insert("/root");
+ test_conf_files_insert("/root/");
+
return 0;
}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index 7335ad6666..2921338f62 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -2,12 +2,12 @@
#include "conf-parser.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_config_parse_path_one(const char *rvalue, const char *expected) {
@@ -236,6 +236,18 @@ static const char* const config_file[] = {
"3\n",
"[Section]\n"
+ "#hogehoge\\\n" /* continuation is ignored in comment */
+ "setting1=1\\\n" /* normal continuation */
+ "2\\\n"
+ "3\n",
+
+ "[Section]\n"
+ "setting1=1\\\n" /* normal continuation */
+ "#hogehoge\\\n" /* commented out line in continuation is ignored */
+ "2\\\n"
+ "3\n",
+
+ "[Section]\n"
"setting1=1\\\n" /* continuation with extra trailing backslash at the end */
"2\\\n"
"3\\\n",
@@ -272,9 +284,9 @@ static const char* const config_file[] = {
static void test_config_parse(unsigned i, const char *s) {
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
- int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *setting1 = NULL;
+ int r;
const ConfigTableItem items[] = {
{ "Section", "setting1", config_parse_string, 0, &setting1},
@@ -283,12 +295,9 @@ static void test_config_parse(unsigned i, const char *s) {
log_info("== %s[%i] ==", __func__, i);
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se((size_t) write(fd, s, strlen(s)) == strlen(s));
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(f = fdopen(fd, "r"));
+ assert_se(fmkostemp_safe(name, "r+", &f) == 0);
+ assert_se(fwrite(s, strlen(s), 1, f) == 1);
+ rewind(f);
/*
int config_parse(const char *unit,
@@ -314,27 +323,27 @@ static void test_config_parse(unsigned i, const char *s) {
assert_se(streq(setting1, "1"));
break;
- case 4 ... 5:
+ case 4 ... 7:
assert_se(r == 0);
assert_se(streq(setting1, "1 2 3"));
break;
- case 6:
+ case 8:
assert_se(r == 0);
assert_se(streq(setting1, "1\\\\ \\\\2"));
break;
- case 7:
+ case 9:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD")));
break;
- case 8 ... 9:
+ case 10 ... 11:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD") " foobar"));
break;
- case 10 ... 11:
+ case 12 ... 13:
assert_se(r == -ENOBUFS);
assert_se(setting1 == NULL);
break;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 2e8d251ac1..b17a1c53fe 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -14,6 +14,8 @@
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
@@ -254,7 +256,7 @@ static void test_copy_atomic(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
test_copy_file();
test_copy_file_fd();
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index c8a83f0fc9..a4b96da045 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -7,7 +7,7 @@
#include "parse-util.h"
#include "strv.h"
-int main(int argc, char*argv[]) {
+int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **l = NULL;
int n, i;
usec_t duration = USEC_PER_SEC / 10;
diff --git a/src/test/test-date.c b/src/test/test-date.c
index 99b6f2eb9e..cba51e225c 100644
--- a/src/test/test-date.c
+++ b/src/test/test-date.c
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "string-util.h"
+#include "tests.h"
#include "util.h"
static void test_should_pass(const char *p) {
@@ -66,9 +67,7 @@ static void test_one_noutc(const char *p) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_one("17:41");
test_one("18:42:44");
diff --git a/src/test/test-dev-setup.c b/src/test/test-dev-setup.c
new file mode 100644
index 0000000000..9414ea6c3e
--- /dev/null
+++ b/src/test/test-dev-setup.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "capability-util.h"
+#include "dev-setup.h"
+#include "fs-util.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "tmpfile-util.h"
+
+int main(int argc, char *argv[]) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ const char *f;
+ struct stat st;
+
+ if (have_effective_cap(CAP_DAC_OVERRIDE) <= 0)
+ return EXIT_TEST_SKIP;
+
+ assert_se(mkdtemp_malloc("/tmp/test-dev-setupXXXXXX", &p) >= 0);
+
+ f = prefix_roota(p, "/run");
+ assert_se(mkdir(f, 0755) >= 0);
+
+ assert_se(make_inaccessible_nodes(p, 1, 1) >= 0);
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/reg");
+ assert_se(stat(f, &st) >= 0);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/dir");
+ assert_se(stat(f, &st) >= 0);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/fifo");
+ assert_se(stat(f, &st) >= 0);
+ assert_se(S_ISFIFO(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/sock");
+ assert_se(stat(f, &st) >= 0);
+ assert_se(S_ISSOCK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/chr");
+ if (stat(f, &st) < 0)
+ assert_se(errno == ENOENT);
+ else {
+ assert_se(S_ISCHR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+ }
+
+ f = prefix_roota(p, "/run/systemd/inaccessible/blk");
+ if (stat(f, &st) < 0)
+ assert_se(errno == ENOENT);
+ else {
+ assert_se(S_ISBLK(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0000);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c
index 02496a121d..ad8d9ace16 100644
--- a/src/test/test-device-nodes.c
+++ b/src/test/test-device-nodes.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Dave Reisner
-***/
#include <sys/types.h>
diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c
index a0a909baf0..7b32e8373f 100644
--- a/src/test/test-dissect-image.c
+++ b/src/test/test-dissect-image.c
@@ -7,13 +7,14 @@
#include "log.h"
#include "loop-util.h"
#include "string-util.h"
+#include "tests.h"
int main(int argc, char *argv[]) {
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
int r, i;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
if (argc < 2) {
log_error("Requires one command line argument.");
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 8ed7dbd1e6..ead5311705 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -1,45 +1,70 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- ***/
#include "alloc-util.h"
#include "dns-domain.h"
#include "macro.h"
#include "string-util.h"
+#include "tests.h"
-static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
+static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret, int ret_ldh) {
char buffer[buffer_sz];
int r;
+ const char *w = what;
- r = dns_label_unescape(&what, buffer, buffer_sz);
+ log_info("%s, %s, %zu, →%d/%d", what, expect, buffer_sz, ret, ret_ldh);
+
+ r = dns_label_unescape(&w, buffer, buffer_sz, 0);
assert_se(r == ret);
+ if (r >= 0)
+ assert_se(streq(buffer, expect));
- if (r < 0)
- return;
+ w = what;
+ r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_LDH);
+ assert_se(r == ret_ldh);
+ if (r >= 0)
+ assert_se(streq(buffer, expect));
- assert_se(streq(buffer, expect));
+ w = what;
+ r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_NO_ESCAPES);
+ const int ret_noe = strchr(what, '\\') ? -EINVAL : ret;
+ assert_se(r == ret_noe);
+ if (r >= 0)
+ assert_se(streq(buffer, expect));
}
static void test_dns_label_unescape(void) {
- test_dns_label_unescape_one("hallo", "hallo", 6, 5);
- 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);
- test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL);
- test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL);
- test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7);
- test_dns_label_unescape_one(".", "", 20, 0);
- 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);
+ log_info("/* %s */", __func__);
+
+ test_dns_label_unescape_one("hallo", "hallo", 6, 5, 5);
+ test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS, -ENOBUFS);
+ test_dns_label_unescape_one("", "", 10, 0, 0);
+ test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12, -EINVAL);
+ test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5, 5);
+ test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7, -EINVAL);
+ test_dns_label_unescape_one(".", "", 20, 0, 0);
+ test_dns_label_unescape_one("..", "", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_one(".foobar", "", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_one("foobar.", "foobar", 20, 6, 6);
+ test_dns_label_unescape_one("foobar..", "foobar", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_one("foo-bar", "foo-bar", 20, 7, 7);
+ test_dns_label_unescape_one("foo-", "foo-", 20, 4, -EINVAL);
+ test_dns_label_unescape_one("-foo", "-foo", 20, 4, -EINVAL);
+ test_dns_label_unescape_one("-foo-", "-foo-", 20, 5, -EINVAL);
+ test_dns_label_unescape_one("foo-.", "foo-", 20, 4, -EINVAL);
+ test_dns_label_unescape_one("foo.-", "foo", 20, 3, 3);
+ test_dns_label_unescape_one("foo\\032", "foo ", 20, 4, -EINVAL);
+ test_dns_label_unescape_one("foo\\045", "foo-", 20, 4, -EINVAL);
+ test_dns_label_unescape_one("głąb", "głąb", 20, 6, -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;
+ log_info("%s, %s, %zu, →%d", what, expect, buffer_sz, ret);
+
r = dns_name_to_wire_format(what, buffer, buffer_sz, false);
assert_se(r == ret);
@@ -81,6 +106,8 @@ static void test_dns_name_to_wire_format(void) {
9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
3, 'a', '1', '2', 0 };
+ log_info("/* %s */", __func__);
+
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));
@@ -101,6 +128,8 @@ static void test_dns_label_unescape_suffix_one(const char *what, const char *exp
const char *label;
int r;
+ log_info("%s, %s, %s, %zu, %d, %d", what, expect1, expect2, buffer_sz, ret1, ret2);
+
label = what + strlen(what);
r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
@@ -115,6 +144,8 @@ static void test_dns_label_unescape_suffix_one(const char *what, const char *exp
}
static void test_dns_label_unescape_suffix(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -140,6 +171,8 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
_cleanup_free_ char *t = NULL;
int r;
+ log_info("%s, %zu, %s, →%d", what, l, expect, ret);
+
r = dns_label_escape_new(what, l, &t);
assert_se(r == ret);
@@ -150,6 +183,8 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
}
static void test_dns_label_escape(void) {
+ log_info("/* %s */", __func__);
+
test_dns_label_escape_one("", 0, NULL, -EINVAL);
test_dns_label_escape_one("hallo", 5, "hallo", 5);
test_dns_label_escape_one("hallo", 6, "hallo\\000", 9);
@@ -160,7 +195,7 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
_cleanup_free_ char *t = NULL;
int r;
- r = dns_name_normalize(what, &t);
+ r = dns_name_normalize(what, 0, &t);
assert_se(r == ret);
if (r < 0)
@@ -321,7 +356,7 @@ static void test_dns_name_reverse(void) {
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(dns_name_concat(a, b, 0, &p) == r);
assert_se(streq_ptr(p, result));
}
@@ -340,46 +375,68 @@ static void test_dns_name_concat(void) {
test_dns_name_concat_one(NULL, "foo", 0, "foo");
}
-static void test_dns_name_is_valid_one(const char *s, int ret) {
+static void test_dns_name_is_valid_one(const char *s, int ret, int ret_ldh) {
+ log_info("%s, →%d", s, ret);
+
assert_se(dns_name_is_valid(s) == ret);
+ assert_se(dns_name_is_valid_ldh(s) == ret_ldh);
}
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);
+ log_info("/* %s */", __func__);
+
+ test_dns_name_is_valid_one("foo", 1, 1);
+ test_dns_name_is_valid_one("foo.", 1, 1);
+ test_dns_name_is_valid_one("foo..", 0, 0);
+ test_dns_name_is_valid_one("Foo", 1, 1);
+ test_dns_name_is_valid_one("foo.bar", 1, 1);
+ test_dns_name_is_valid_one("foo.bar.baz", 1, 1);
+ test_dns_name_is_valid_one("", 1, 1);
+ test_dns_name_is_valid_one("foo..bar", 0, 0);
+ test_dns_name_is_valid_one(".foo.bar", 0, 0);
+ test_dns_name_is_valid_one("foo.bar.", 1, 1);
+ test_dns_name_is_valid_one("foo.bar..", 0, 0);
+ test_dns_name_is_valid_one("\\zbar", 0, 0);
+ test_dns_name_is_valid_one("ä", 1, 0);
+ test_dns_name_is_valid_one("\n", 0, 0);
+
+ test_dns_name_is_valid_one("dash-", 1, 0);
+ test_dns_name_is_valid_one("-dash", 1, 0);
+ test_dns_name_is_valid_one("dash-dash", 1, 1);
+ test_dns_name_is_valid_one("foo.dash-", 1, 0);
+ test_dns_name_is_valid_one("foo.-dash", 1, 0);
+ test_dns_name_is_valid_one("foo.dash-dash", 1, 1);
+ test_dns_name_is_valid_one("foo.dash-.bar", 1, 0);
+ test_dns_name_is_valid_one("foo.-dash.bar", 1, 0);
+ test_dns_name_is_valid_one("foo.dash-dash.bar", 1, 1);
+ test_dns_name_is_valid_one("dash-.bar", 1, 0);
+ test_dns_name_is_valid_one("-dash.bar", 1, 0);
+ test_dns_name_is_valid_one("dash-dash.bar", 1, 1);
+ test_dns_name_is_valid_one("-.bar", 1, 0);
+ test_dns_name_is_valid_one("foo.-", 1, 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);
+ 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, 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);
+ 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, 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);
+ 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, 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);
+ 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, 1);
/* label of 64 chars length */
- test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0);
+ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0, 0);
/* label of 63 chars length */
- test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1);
+ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1, 1);
}
static void test_dns_service_name_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(dns_service_name_is_valid("Lennart's Compüter"));
assert_se(dns_service_name_is_valid("piff.paff"));
@@ -391,6 +448,7 @@ static void test_dns_service_name_is_valid(void) {
}
static void test_dns_srv_type_is_valid(void) {
+ log_info("/* %s */", __func__);
assert_se(dns_srv_type_is_valid("_http._tcp"));
assert_se(dns_srv_type_is_valid("_foo-bar._tcp"));
@@ -414,6 +472,7 @@ static void test_dns_srv_type_is_valid(void) {
}
static void test_dnssd_srv_type_is_valid(void) {
+ log_info("/* %s */", __func__);
assert_se(dnssd_srv_type_is_valid("_http._tcp"));
assert_se(dnssd_srv_type_is_valid("_foo-bar._tcp"));
@@ -440,6 +499,8 @@ static void test_dnssd_srv_type_is_valid(void) {
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;
+ log_info("%s, %s, %s, →%d, %s", a, b, c, r, d);
+
assert_se(dns_service_join(a, b, c, &t) == r);
assert_se(streq_ptr(t, d));
@@ -453,6 +514,8 @@ static void test_dns_service_join_one(const char *a, const char *b, const char *
}
static void test_dns_service_join(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -470,6 +533,8 @@ static void test_dns_service_join(void) {
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;
+ log_info("%s, %s, %s, %s, →%d", joined, a, b, c, r);
+
assert_se(dns_service_split(joined, &x, &y, &z) == r);
assert_se(streq_ptr(x, a));
assert_se(streq_ptr(y, b));
@@ -486,6 +551,8 @@ static void test_dns_service_split_one(const char *joined, const char *a, const
}
static void test_dns_service_split(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -498,11 +565,15 @@ static void test_dns_service_split(void) {
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;
+ log_info("%s, %s, %s, →%s", name, old_suffix, new_suffix, result);
+
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) {
+ log_info("/* %s */", __func__);
+
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");
@@ -517,11 +588,15 @@ static void test_dns_name_change_suffix(void) {
static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) {
const char *p = NULL;
+ log_info("%s, %d, →%s, %d", name, n_labels, result, ret);
+
assert_se(ret == dns_name_suffix(name, n_labels, &p));
assert_se(streq_ptr(p, result));
}
static void test_dns_name_suffix(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -539,10 +614,14 @@ static void test_dns_name_suffix(void) {
}
static void test_dns_name_count_labels_one(const char *name, int n) {
+ log_info("%s, →%d", name, n);
+
assert_se(dns_name_count_labels(name) == n);
}
static void test_dns_name_count_labels(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -555,10 +634,14 @@ static void test_dns_name_count_labels(void) {
}
static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) {
+ log_info("%s, %u, %s, →%d", a, n_labels, b, ret);
+
assert_se(dns_name_equal_skip(a, n_labels, b) == ret);
}
static void test_dns_name_equal_skip(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -586,6 +669,8 @@ static void test_dns_name_equal_skip(void) {
}
static void test_dns_name_compare_func(void) {
+ log_info("/* %s */", __func__);
+
assert_se(dns_name_compare_func("", "") == 0);
assert_se(dns_name_compare_func("", ".") == 0);
assert_se(dns_name_compare_func(".", "") == 0);
@@ -601,11 +686,15 @@ static void test_dns_name_compare_func(void) {
static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) {
const char *c;
+ log_info("%s, %s, →%s", a, b, result);
+
assert_se(dns_name_common_suffix(a, b, &c) >= 0);
assert_se(streq(c, result));
}
static void test_dns_name_common_suffix(void) {
+ log_info("/* %s */", __func__);
+
test_dns_name_common_suffix_one("", "", "");
test_dns_name_common_suffix_one("foo", "", "");
test_dns_name_common_suffix_one("", "foo", "");
@@ -640,6 +729,7 @@ static void test_dns_name_apply_idna(void) {
#else
const int ret = 0;
#endif
+ log_info("/* %s */", __func__);
/* IDNA2008 forbids names with hyphens in third and fourth positions
* (https://tools.ietf.org/html/rfc5891#section-4.2.3.1).
@@ -677,6 +767,8 @@ static void test_dns_name_apply_idna(void) {
}
static void test_dns_name_is_valid_or_address(void) {
+ log_info("/* %s */", __func__);
+
assert_se(dns_name_is_valid_or_address(NULL) == 0);
assert_se(dns_name_is_valid_or_address("") == 0);
assert_se(dns_name_is_valid_or_address("foobar") > 0);
@@ -689,9 +781,7 @@ static void test_dns_name_is_valid_or_address(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_dns_label_unescape();
test_dns_label_unescape_suffix();
diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c
new file mode 100644
index 0000000000..8ce28ed9f5
--- /dev/null
+++ b/src/test/test-emergency-action.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "emergency-action.h"
+#include "tests.h"
+
+static void test_parse_emergency_action(void) {
+ EmergencyAction x;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(parse_emergency_action("none", false, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_NONE);
+ assert_se(parse_emergency_action("reboot", false, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("reboot-force", false, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("reboot-immediate", false, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("poweroff", false, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("poweroff-force", false, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("poweroff-immediate", false, &x) == -EOPNOTSUPP);
+ assert_se(x == EMERGENCY_ACTION_NONE);
+ assert_se(parse_emergency_action("exit", false, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_EXIT);
+ assert_se(parse_emergency_action("exit-force", false, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_EXIT_FORCE);
+ assert_se(parse_emergency_action("exit-forcee", false, &x) == -EINVAL);
+
+ assert_se(parse_emergency_action("none", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_NONE);
+ assert_se(parse_emergency_action("reboot", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_REBOOT);
+ assert_se(parse_emergency_action("reboot-force", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_REBOOT_FORCE);
+ assert_se(parse_emergency_action("reboot-immediate", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_REBOOT_IMMEDIATE);
+ assert_se(parse_emergency_action("poweroff", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_POWEROFF);
+ assert_se(parse_emergency_action("poweroff-force", true, &x) == 0);
+ assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE);
+ assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0);
+ assert_se(parse_emergency_action("exit", true, &x) == 0);
+ assert_se(parse_emergency_action("exit-force", true, &x) == 0);
+ assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL);
+ assert_se(x == EMERGENCY_ACTION_EXIT_FORCE);
+}
+
+int main(int argc, char **argv) {
+ test_setup_logging(LOG_INFO);
+
+ test_parse_emergency_action();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index d072a15cb1..0673d36b62 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -18,24 +18,18 @@ int main(int argc, char *argv[]) {
Job *j;
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice_errno(r, "Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
/* prepare the test */
- assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(set_unit_path(get_testdata_dir()) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
- if (MANAGER_SKIP_TEST(r)) {
- log_notice_errno(r, "Skipping test: manager_new: %m");
- return EXIT_TEST_SKIP;
- }
+ if (MANAGER_SKIP_TEST(r))
+ return log_tests_skipped_errno(r, "manager_new");
assert_se(r >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c
index e645d4968e..f57a26021c 100644
--- a/src/test/test-env-util.c
+++ b/src/test/test-env-util.c
@@ -5,6 +5,8 @@
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "serialize.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -12,13 +14,13 @@
static void test_strv_env_delete(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
- a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL);
+ a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
assert_se(a);
- b = strv_new("PIEP", "FOO", NULL);
+ b = strv_new("PIEP", "FOO");
assert_se(b);
- c = strv_new("SCHLUMPF", NULL);
+ c = strv_new("SCHLUMPF");
assert_se(c);
d = strv_env_delete(a, 2, b, c);
@@ -42,7 +44,7 @@ static void test_strv_env_get(void) {
static void test_strv_env_unset(void) {
_cleanup_strv_free_ char **l = NULL;
- l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
+ l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
assert_se(l);
assert_se(strv_env_unset(l, "SCHLUMPF") == l);
@@ -55,7 +57,7 @@ static void test_strv_env_unset(void) {
static void test_strv_env_set(void) {
_cleanup_strv_free_ char **l = NULL, **r = NULL;
- l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
+ l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
assert_se(l);
r = strv_env_set(l, "WALDO=WALDO");
@@ -71,10 +73,10 @@ static void test_strv_env_set(void) {
static void test_strv_env_merge(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL;
- a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL);
+ a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
assert_se(a);
- b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
+ b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
assert_se(b);
r = strv_env_merge(2, a, b);
@@ -247,8 +249,7 @@ static void test_env_clean(void) {
"xyz\n=xyz",
"xyz=xyz\n",
"another=one",
- "another=final one",
- NULL);
+ "another=final one");
assert_se(e);
assert_se(!strv_env_is_valid(e));
assert_se(strv_env_clean(e) == e);
@@ -303,61 +304,6 @@ static void test_env_assignment_is_valid(void) {
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
}
-static void test_deserialize_environment(void) {
- _cleanup_strv_free_ char **env = strv_new("A=1", NULL);
-
- assert_se(deserialize_environment(&env, "env=B=2") >= 0);
- assert_se(deserialize_environment(&env, "env=FOO%%=a\\177b\\nc\\td e") >= 0);
-
- assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e")));
-
- assert_se(deserialize_environment(&env, "env=foo\\") < 0);
- assert_se(deserialize_environment(&env, "env=bar\\_baz") < 0);
-}
-
-static void test_serialize_environment(void) {
- char fn[] = "/tmp/test-env-util.XXXXXXX";
- int fd, r;
- _cleanup_fclose_ FILE *f = NULL;
-
- _cleanup_strv_free_ char **env = strv_new("A=1",
- "B=2",
- "C=ąęółń",
- "D=D=a\\x0Ab",
- "FOO%%=a\177b\nc\td e",
- NULL);
- _cleanup_strv_free_ char **env2 = NULL;
-
- fd = mkostemp_safe(fn);
- assert_se(fd >= 0);
-
- assert_se(f = fdopen(fd, "r+"));
-
- assert_se(serialize_environment(f, env) == 0);
- assert_se(fflush_and_check(f) == 0);
-
- rewind(f);
-
- for (;;) {
- char line[LINE_MAX];
- const char *l;
-
- if (!fgets(line, sizeof line, f))
- break;
-
- char_array_0(line);
- l = strstrip(line);
-
- r = deserialize_environment(&env2, l);
- assert_se(r == 1);
- }
- assert_se(feof(f));
-
- assert_se(strv_equal(env, env2));
-
- unlink(fn);
-}
-
int main(int argc, char *argv[]) {
test_strv_env_delete();
test_strv_env_get();
@@ -374,8 +320,6 @@ int main(int argc, char *argv[]) {
test_env_name_is_valid();
test_env_value_is_valid();
test_env_assignment_is_valid();
- test_deserialize_environment();
- test_serialize_environment();
return 0;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
index 650a9a058d..4ee4aa974d 100644
--- a/src/test/test-escape.c
+++ b/src/test/test-escape.c
@@ -3,6 +3,7 @@
#include "alloc-util.h"
#include "escape.h"
#include "macro.h"
+#include "tests.h"
static void test_cescape(void) {
_cleanup_free_ char *escaped;
@@ -119,9 +120,7 @@ static void test_shell_maybe_quote(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_cescape();
test_cunescape();
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
index cfc8b5f88e..21a4538d74 100644
--- a/src/test/test-exec-util.c
+++ b/src/test/test-exec-util.c
@@ -16,9 +16,11 @@
#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
static int here = 0, here2 = 0, here3 = 0;
void *ignore_stdout_args[] = {&here, &here2, &here3};
@@ -115,9 +117,9 @@ static void test_execute_directory(bool gather_stdout) {
assert_se(chmod(mask2e, 0755) == 0);
if (gather_stdout)
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
else
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL);
assert_se(chdir(template_lo) == 0);
assert_se(access("it_works", F_OK) >= 0);
@@ -182,7 +184,7 @@ static void test_execution_order(void) {
assert_se(chmod(override, 0755) == 0);
assert_se(chmod(masked, 0755) == 0);
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+ execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
assert_se(read_full_file(output, &contents, NULL) >= 0);
assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n"));
@@ -264,7 +266,7 @@ static void test_stdout_gathering(void) {
assert_se(chmod(name2, 0755) == 0);
assert_se(chmod(name3, 0755) == 0);
- r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL);
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL);
assert_se(r >= 0);
log_info("got: %s", output);
@@ -275,7 +277,7 @@ static void test_stdout_gathering(void) {
static void test_environment_gathering(void) {
char template[] = "/tmp/test-exec-util.XXXXXXX", **p;
const char *dirs[] = {template, NULL};
- const char *name, *name2, *name3;
+ const char *name, *name2, *name3, *old;
int r;
char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
@@ -321,7 +323,33 @@ static void test_environment_gathering(void) {
assert_se(chmod(name2, 0755) == 0);
assert_se(chmod(name3, 0755) == 0);
- r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+ /* When booting in containers or without initramfs there might not be
+ * any PATH in the environ and if there is no PATH /bin/sh built-in
+ * PATH may leak and override systemd's DEFAULT_PATH which is not
+ * good. Force our own PATH in environment, to prevent expansion of sh
+ * built-in $PATH */
+ old = getenv("PATH");
+ r = setenv("PATH", "no-sh-built-in-path", 1);
+ assert_se(r >= 0);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL);
+ assert_se(r >= 0);
+
+ STRV_FOREACH(p, env)
+ log_info("got env: \"%s\"", *p);
+
+ assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
+ assert_se(streq(strv_env_get(env, "B"), "12"));
+ assert_se(streq(strv_env_get(env, "C"), "001"));
+ assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file"));
+
+ /* now retest with "default" path passed in, as created by
+ * manager_default_environment */
+ env = strv_free(env);
+ env = strv_new("PATH=" DEFAULT_PATH);
+ assert_se(env);
+
+ r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env);
assert_se(r >= 0);
STRV_FOREACH(p, env)
@@ -330,13 +358,14 @@ static void test_environment_gathering(void) {
assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
assert_se(streq(strv_env_get(env, "B"), "12"));
assert_se(streq(strv_env_get(env, "C"), "001"));
- assert_se(endswith(strv_env_get(env, "PATH"), ":/no/such/file"));
+ assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file"));
+
+ /* reset environ PATH */
+ (void) setenv("PATH", old, 1);
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_execute_directory(true);
test_execute_directory(false);
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index fa8efdddd2..2115061add 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -28,6 +28,8 @@
#include "util.h"
#include "virt.h"
+static bool can_unshare;
+
typedef void (*test_function_t)(Manager *m);
static void check(Manager *m, Unit *unit, int status_expected, int code_expected) {
@@ -52,6 +54,9 @@ static void check(Manager *m, Unit *unit, int status_expected, int code_expected
n = now(CLOCK_MONOTONIC);
if (ts + timeout < n) {
log_error("Test timeout when testing %s", unit->id);
+ r = unit_kill(unit, KILL_ALL, SIGKILL, NULL);
+ if (r < 0)
+ log_error_errno(r, "Failed to kill %s: %m", unit->id);
exit(EXIT_FAILURE);
}
}
@@ -105,6 +110,25 @@ invalid:
return false;
}
+static bool check_user_has_group_with_same_name(const char *name) {
+ struct passwd *p;
+ struct group *g;
+
+ assert(name);
+
+ p = getpwnam(name);
+ if (!p ||
+ !streq(p->pw_name, name))
+ return false;
+
+ g = getgrgid(p->pw_gid);
+ if (!g ||
+ !streq(g->gr_name, name))
+ return false;
+
+ return true;
+}
+
static bool is_inaccessible_available(void) {
char *p;
@@ -129,7 +153,7 @@ static void test(Manager *m, const char *unit_name, int status_expected, int cod
assert_se(unit_name);
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
check(m, unit, status_expected, code_expected);
}
@@ -137,7 +161,7 @@ static void test_exec_bindpaths(Manager *m) {
assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
- test(m, "exec-bindpaths.service", 0, CLD_EXITED);
+ test(m, "exec-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -208,7 +232,7 @@ static void test_exec_ignoresigpipe(Manager *m) {
static void test_exec_privatetmp(Manager *m) {
assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
- test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED);
+ test(m, "exec-privatetmp-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-privatetmp-no.service", 0, CLD_EXITED);
unlink("/tmp/test-exec_privatetmp");
@@ -226,9 +250,9 @@ static void test_exec_privatedevices(Manager *m) {
return;
}
- test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
+ test(m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
- test(m, "exec-privatedevices-disabled-by-prefix.service", 0, CLD_EXITED);
+ test(m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
/* We use capsh to test if the capabilities are
* properly set, so be sure that it exists */
@@ -264,21 +288,21 @@ static void test_exec_protectkernelmodules(Manager *m) {
test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
- test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
+ test(m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_readonlypaths(Manager *m) {
- test(m, "exec-readonlypaths-simple.service", 0, CLD_EXITED);
+ test(m, "exec-readonlypaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
if (path_is_read_only_fs("/var") > 0) {
log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
return;
}
- test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
- test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
- test(m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
+ test(m, "exec-readonlypaths.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
+ test(m, "exec-readonlypaths-with-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-readonlypaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_readwritepaths(Manager *m) {
@@ -288,7 +312,7 @@ static void test_exec_readwritepaths(Manager *m) {
return;
}
- test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
+ test(m, "exec-readwritepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_inaccessiblepaths(Manager *m) {
@@ -298,26 +322,28 @@ static void test_exec_inaccessiblepaths(Manager *m) {
return;
}
- test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
+ test(m, "exec-inaccessiblepaths-proc.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
if (path_is_read_only_fs("/") > 0) {
log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
return;
}
- test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
+ test(m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_temporaryfilesystem(Manager *m) {
- test(m, "exec-temporaryfilesystem-options.service", 0, CLD_EXITED);
- test(m, "exec-temporaryfilesystem-ro.service", 0, CLD_EXITED);
- test(m, "exec-temporaryfilesystem-rw.service", 0, CLD_EXITED);
- test(m, "exec-temporaryfilesystem-usr.service", 0, CLD_EXITED);
+ test(m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-temporaryfilesystem-ro.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-temporaryfilesystem-rw.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-temporaryfilesystem-usr.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
}
static void test_exec_systemcallfilter(Manager *m) {
#if HAVE_SECCOMP
+ int r;
+
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
@@ -327,18 +353,34 @@ static void test_exec_systemcallfilter(Manager *m) {
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);
+
+ r = find_binary("python3", NULL);
+ if (r < 0) {
+ log_notice_errno(r, "Skipping remaining tests in %s, could not find python3 binary: %m", __func__);
+ return;
+ }
+
test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
+ test(m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
#endif
}
static void test_exec_systemcallerrornumber(Manager *m) {
#if HAVE_SECCOMP
+ int r;
+
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
+ r = find_binary("python3", NULL);
+ if (r < 0) {
+ log_notice_errno(r, "Skipping %s, could not find python3 binary: %m", __func__);
+ return;
+ }
+
test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
#endif
@@ -351,13 +393,13 @@ static void test_exec_restrictnamespaces(Manager *m) {
return;
}
- test(m, "exec-restrictnamespaces-no.service", 0, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-no.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
- test(m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-mnt.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
- test(m, "exec-restrictnamespaces-merge-and.service", 0, CLD_EXITED);
- test(m, "exec-restrictnamespaces-merge-or.service", 0, CLD_EXITED);
- test(m, "exec-restrictnamespaces-merge-all.service", 0, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-and.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-or.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-all.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
#endif
}
@@ -426,10 +468,15 @@ static void test_exec_supplementarygroups(Manager *m) {
}
static void test_exec_dynamicuser(Manager *m) {
- test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
- test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
- test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
- test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
+
+ test(m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ if (check_user_has_group_with_same_name("adm"))
+ test(m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ if (check_user_has_group_with_same_name("games"))
+ test(m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
+ test(m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -437,7 +484,7 @@ static void test_exec_dynamicuser(Manager *m) {
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
- test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
+ test(m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -595,19 +642,29 @@ static void test_exec_privatenetwork(Manager *m) {
return;
}
- test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
+ test(m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED);
}
static void test_exec_oomscoreadjust(Manager *m) {
test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
+
+ if (detect_container() > 0) {
+ log_notice("Testing in container, skipping remaining tests in %s", __func__);
+ return;
+ }
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);
+
+ if (detect_container() > 0) {
+ log_notice("Testing in container, skipping remaining tests in %s", __func__);
+ return;
+ }
+ test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
}
static void test_exec_unsetenvironment(Manager *m) {
@@ -625,6 +682,14 @@ static void test_exec_standardinput(Manager *m) {
test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
}
+static void test_exec_standardoutput(Manager *m) {
+ test(m, "exec-standardoutput-file.service", 0, CLD_EXITED);
+}
+
+static void test_exec_standardoutput_append(Manager *m) {
+ test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
+}
+
static int run_tests(UnitFileScope scope, const test_function_t *tests) {
const test_function_t *test = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
@@ -633,10 +698,8 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
assert_se(tests);
r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m);
- if (MANAGER_SKIP_TEST(r)) {
- log_notice_errno(r, "Skipping test: manager_new: %m");
- return EXIT_TEST_SKIP;
- }
+ if (MANAGER_SKIP_TEST(r))
+ return log_tests_skipped_errno(r, "manager_new");
assert_se(r >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
@@ -648,6 +711,8 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ _cleanup_free_ char *test_execute_path = NULL;
+ _cleanup_hashmap_free_ Hashmap *s = NULL;
static const test_function_t user_tests[] = {
test_exec_basic,
test_exec_ambientcapabilities,
@@ -672,6 +737,8 @@ int main(int argc, char *argv[]) {
test_exec_restrictnamespaces,
test_exec_runtimedirectory,
test_exec_standardinput,
+ test_exec_standardoutput,
+ test_exec_standardoutput_append,
test_exec_supplementarygroups,
test_exec_systemcallerrornumber,
test_exec_systemcallfilter,
@@ -690,28 +757,32 @@ int main(int argc, char *argv[]) {
};
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
+
+#if HAS_FEATURE_ADDRESS_SANITIZER
+ if (is_run_on_travis_ci()) {
+ log_notice("Running on TravisCI under ASan, skipping, see https://github.com/systemd/systemd/issues/10696");
+ return EXIT_TEST_SKIP;
+ }
+#endif
(void) unsetenv("USER");
(void) unsetenv("LOGNAME");
(void) unsetenv("SHELL");
+ can_unshare = have_namespaces();
+
/* It is needed otherwise cgroup creation fails */
- if (getuid() != 0) {
- puts("Skipping test: not root");
- return EXIT_TEST_SKIP;
- }
+ if (getuid() != 0)
+ return log_tests_skipped("not root");
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- puts("Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir());
- assert_se(set_unit_path(get_testdata_dir("/test-execute")) >= 0);
+ test_execute_path = path_join(get_testdata_dir(), "test-execute");
+ assert_se(set_unit_path(test_execute_path) >= 0);
/* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
* cases, otherwise (and if they are present in the environment),
@@ -727,5 +798,33 @@ int main(int argc, char *argv[]) {
if (r != 0)
return r;
+ r = run_tests(UNIT_FILE_SYSTEM, system_tests);
+ if (r != 0)
+ return r;
+
+#if HAVE_SECCOMP
+ /* The following tests are for 1beab8b0d0ff2d7d1436b52d4a0c3d56dc908962. */
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping unshare() filtered tests.");
+ return 0;
+ }
+
+ assert_se(s = hashmap_new(NULL));
+ r = seccomp_syscall_resolve_name("unshare");
+ assert_se(r != __NR_SCMP_ERROR);
+ assert_se(hashmap_put(s, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true) >= 0);
+ assert_se(unshare(CLONE_NEWNS) < 0);
+ assert_se(errno == EOPNOTSUPP);
+
+ can_unshare = false;
+
+ r = run_tests(UNIT_FILE_USER, user_tests);
+ if (r != 0)
+ return r;
+
return run_tests(UNIT_FILE_SYSTEM, system_tests);
+#else
+ return 0;
+#endif
}
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
index a04403d748..7a0a2ad7d8 100644
--- a/src/test/test-fd-util.c
+++ b/src/test/test-fd-util.c
@@ -10,7 +10,10 @@
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
+#include "serialize.h"
#include "string-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_close_many(void) {
@@ -316,7 +319,7 @@ static void test_read_nr_open(void) {
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
test_close_many();
test_close_nointr();
diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c
index 7d68a6b966..fb9d397569 100644
--- a/src/test/test-fdset.c
+++ b/src/test/test-fdset.c
@@ -5,8 +5,8 @@
#include "fd-util.h"
#include "fdset.h"
-#include "fileio.h"
#include "macro.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_fdset_new_fill(void) {
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 14ba075144..bf918c1d1e 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -6,7 +6,7 @@
#include "alloc-util.h"
#include "ctype.h"
-#include "def.h"
+#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -16,30 +16,23 @@
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_parse_env_file(void) {
_cleanup_(unlink_tempfilep) char
t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
- int fd, r;
FILE *f;
_cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
*six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
_cleanup_strv_free_ char **a = NULL, **b = NULL;
char **i;
unsigned k;
+ int r;
- fd = mkostemp_safe(p);
- assert_se(fd >= 0);
- close(fd);
-
- fd = mkostemp_safe(t);
- assert_se(fd >= 0);
-
- f = fdopen(fd, "w");
- assert_se(f);
-
+ assert_se(fmkostemp_safe(t, "w", &f) == 0);
fputs("one=BAR \n"
"# comment\n"
" # comment \n"
@@ -63,7 +56,7 @@ static void test_parse_env_file(void) {
fflush(f);
fclose(f);
- r = load_env_file(NULL, t, NULL, &a);
+ r = load_env_file(NULL, t, &a);
assert_se(r >= 0);
STRV_FOREACH(i, a)
@@ -90,7 +83,7 @@ static void test_parse_env_file(void) {
}
r = parse_env_file(
- NULL, t, NULL,
+ NULL, t,
"one", &one,
"two", &two,
"three", &three,
@@ -100,8 +93,7 @@ static void test_parse_env_file(void) {
"seven", &seven,
"eight", &eight,
"export nine", &nine,
- "ten", &ten,
- NULL);
+ "ten", &ten);
assert_se(r >= 0);
@@ -127,10 +119,16 @@ static void test_parse_env_file(void) {
assert_se(streq(nine, "nineval"));
assert_se(ten == NULL);
+ {
+ /* prepare a temporary file to write the environment to */
+ _cleanup_close_ int fd = mkostemp_safe(p);
+ assert_se(fd >= 0);
+ }
+
r = write_env_file(p, a);
assert_se(r >= 0);
- r = load_env_file(NULL, p, NULL, &b);
+ r = load_env_file(NULL, p, &b);
assert_se(r >= 0);
}
@@ -138,21 +136,12 @@ static void test_parse_multiline_env_file(void) {
_cleanup_(unlink_tempfilep) char
t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
- int fd, r;
FILE *f;
_cleanup_strv_free_ char **a = NULL, **b = NULL;
char **i;
+ int r;
- fd = mkostemp_safe(p);
- assert_se(fd >= 0);
- close(fd);
-
- fd = mkostemp_safe(t);
- assert_se(fd >= 0);
-
- f = fdopen(fd, "w");
- assert_se(f);
-
+ assert_se(fmkostemp_safe(t, "w", &f) == 0);
fputs("one=BAR\\\n"
" VAR\\\n"
"\tGAR\n"
@@ -168,7 +157,7 @@ static void test_parse_multiline_env_file(void) {
fflush(f);
fclose(f);
- r = load_env_file(NULL, t, NULL, &a);
+ r = load_env_file(NULL, t, &a);
assert_se(r >= 0);
STRV_FOREACH(i, a)
@@ -179,28 +168,28 @@ static void test_parse_multiline_env_file(void) {
assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
assert_se(a[3] == NULL);
+ {
+ _cleanup_close_ int fd = mkostemp_safe(p);
+ assert_se(fd >= 0);
+ }
+
r = write_env_file(p, a);
assert_se(r >= 0);
- r = load_env_file(NULL, p, NULL, &b);
+ r = load_env_file(NULL, p, &b);
assert_se(r >= 0);
}
static void test_merge_env_file(void) {
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
- int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
char **i;
+ int r;
- fd = mkostemp_safe(t);
- assert_se(fd >= 0);
-
+ assert_se(fmkostemp_safe(t, "w", &f) == 0);
log_info("/* %s (%s) */", __func__, t);
- f = fdopen(fd, "w");
- assert_se(f);
-
r = write_string_stream(f,
"one=1 \n"
"twelve=${one}2\n"
@@ -257,19 +246,14 @@ static void test_merge_env_file(void) {
static void test_merge_env_file_invalid(void) {
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
- int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
char **i;
+ int r;
- fd = mkostemp_safe(t);
- assert_se(fd >= 0);
-
+ assert_se(fmkostemp_safe(t, "w", &f) == 0);
log_info("/* %s (%s) */", __func__, t);
- f = fdopen(fd, "w");
- assert_se(f);
-
r = write_string_stream(f,
"unset one \n"
"unset one= \n"
@@ -296,16 +280,11 @@ static void test_merge_env_file_invalid(void) {
static void test_executable_is_script(void) {
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
- int fd, r;
_cleanup_fclose_ FILE *f = NULL;
char *command;
+ int r;
- fd = mkostemp_safe(t);
- assert_se(fd >= 0);
-
- f = fdopen(fd, "w");
- assert_se(f);
-
+ assert_se(fmkostemp_safe(t, "w", &f) == 0);
fputs("#! /bin/script -a -b \ngoo goo", f);
fflush(f);
@@ -488,7 +467,7 @@ static void test_load_env_file_pairs(void) {
f = fdopen(fd, "r");
assert_se(f);
- r = load_env_file_pairs(f, fn, NULL, &l);
+ r = load_env_file_pairs(f, fn, &l);
assert_se(r >= 0);
assert_se(strv_length(l) == 14);
@@ -631,8 +610,43 @@ static void test_tempfn(void) {
free(ret);
}
+static const char chars[] =
+ "Aąę„”\n루\377";
+
+static void test_fgetc(void) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char c;
+
+ f = fmemopen((void*) chars, sizeof(chars), "re");
+ assert_se(f);
+
+ for (unsigned i = 0; i < sizeof(chars); i++) {
+ assert_se(safe_fgetc(f, &c) == 1);
+ assert_se(c == chars[i]);
+
+ /* EOF is -1, and hence we can't push value 255 in this way */
+ assert_se(ungetc(c, f) != EOF || c == EOF);
+ assert_se(c == EOF || safe_fgetc(f, &c) == 1);
+ assert_se(c == chars[i]);
+
+ /* But it works when we push it properly cast */
+ assert_se(ungetc((unsigned char) c, f) != EOF);
+ assert_se(safe_fgetc(f, &c) == 1);
+ assert_se(c == chars[i]);
+ }
+
+ assert_se(safe_fgetc(f, &c) == 0);
+}
+
static const char buffer[] =
"Some test data\n"
+ "루Non-ascii chars: ąę„”\n"
+ "terminators\r\n"
+ "and even more\n\r"
+ "now the same with a NUL\n\0"
+ "and more\r\0"
+ "and even more\r\n\0"
+ "and yet even more\n\r\0"
"With newlines, and a NUL byte\0"
"\n"
"an empty line\n"
@@ -645,6 +659,27 @@ static void test_read_line_one_file(FILE *f) {
assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
line = mfree(line);
+ assert_se(read_line(f, (size_t) -1, &line) > 0 && streq(line, "루Non-ascii chars: ąę„”"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 13 && streq(line, "terminators"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "and even more"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 25 && streq(line, "now the same with a NUL"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 10 && streq(line, "and more"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 16 && streq(line, "and even more"));
+ line = mfree(line);
+
+ assert_se(read_line(f, (size_t) -1, &line) == 20 && streq(line, "and yet even more"));
+ line = mfree(line);
+
assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte"));
line = mfree(line);
@@ -661,10 +696,7 @@ static void test_read_line_one_file(FILE *f) {
/* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first
* character after the previous limit. Let's make use of tha to continue our test. */
- assert_se(read_line(f, 1024, &line) == 61 && streq(line, "line that is supposed to be truncated, because it is so long"));
- line = mfree(line);
-
- assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
+ assert_se(read_line(f, 1024, &line) == 62 && streq(line, "line that is supposed to be truncated, because it is so long"));
line = mfree(line);
assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
@@ -709,10 +741,77 @@ static void test_read_line3(void) {
assert_se(read_line(f, LINE_MAX, NULL) == 0);
}
+static void test_read_line4(void) {
+ static const struct {
+ size_t length;
+ const char *string;
+ } eof_endings[] = {
+ /* Each of these will be followed by EOF and should generate the one same single string */
+ { 3, "foo" },
+ { 4, "foo\n" },
+ { 4, "foo\r" },
+ { 4, "foo\0" },
+ { 5, "foo\n\0" },
+ { 5, "foo\r\0" },
+ { 5, "foo\r\n" },
+ { 5, "foo\n\r" },
+ { 6, "foo\r\n\0" },
+ { 6, "foo\n\r\0" },
+ };
+
+ size_t i;
+ int r;
+
+ for (i = 0; i < ELEMENTSOF(eof_endings); i++) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *s = NULL;
+
+ assert_se(f = fmemopen((void*) eof_endings[i].string, eof_endings[i].length, "r"));
+
+ r = read_line(f, (size_t) -1, &s);
+ assert_se((size_t) r == eof_endings[i].length);
+ assert_se(streq_ptr(s, "foo"));
+
+ assert_se(read_line(f, (size_t) -1, NULL) == 0); /* Ensure we hit EOF */
+ }
+}
+
+static void test_read_nul_string(void) {
+ static const char test[] = "string nr. 1\0"
+ "string nr. 2\n\0"
+ "\377empty string follows\0"
+ "\0"
+ "final string\n is empty\0"
+ "\0";
+
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *s = NULL;
+
+ assert_se(f = fmemopen((void*) test, sizeof(test)-1, "r"));
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1"));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 14 && streq_ptr(s, "string nr. 2\n"));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 22 && streq_ptr(s, "\377empty string follows"));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 23 && streq_ptr(s, "final string\n is empty"));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));
+ s = mfree(s);
+
+ assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 0 && streq_ptr(s, ""));
+}
+
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_parse_env_file();
test_parse_multiline_env_file();
@@ -730,9 +829,12 @@ int main(int argc, char *argv[]) {
test_search_and_fopen_nulstr();
test_writing_tmpfile();
test_tempfn();
+ test_fgetc();
test_read_line();
test_read_line2();
test_read_line3();
+ test_read_line4();
+ test_read_nul_string();
return 0;
}
diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c
index 1b62590b49..1788e8d1ca 100644
--- a/src/test/test-firewall-util.c
+++ b/src/test/test-firewall-util.c
@@ -2,12 +2,13 @@
#include "firewall-util.h"
#include "log.h"
+#include "tests.h"
#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
int main(int argc, char *argv[]) {
int r;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0);
if (r < 0)
diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c
index adcc414161..5bede5c75b 100644
--- a/src/test/test-format-table.c
+++ b/src/test/test-format-table.c
@@ -5,6 +5,30 @@
#include "string-util.h"
#include "time-util.h"
+static void test_issue_9549(void) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ _cleanup_free_ char *formatted = NULL;
+
+ assert_se(table = table_new("name", "type", "ro", "usage", "created", "modified"));
+ assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(3), 100) >= 0);
+ assert_se(table_add_many(table,
+ TABLE_STRING, "foooo",
+ TABLE_STRING, "raw",
+ TABLE_BOOLEAN, false,
+ TABLE_SIZE, (uint64_t) (673.7*1024*1024),
+ TABLE_STRING, "Wed 2018-07-11 00:10:33 JST",
+ TABLE_STRING, "Wed 2018-07-11 00:16:00 JST") >= 0);
+
+ table_set_width(table, 75);
+ assert_se(table_format(table, &formatted) >= 0);
+
+ printf("%s\n", formatted);
+ assert_se(streq(formatted,
+ "NAME TYPE RO USAGE CREATED MODIFIED \n"
+ "foooo raw no 673.6M Wed 2018-07-11 00:10:33 J… Wed 2018-07-11 00:16:00 JST\n"
+ ));
+}
+
int main(int argc, char *argv[]) {
_cleanup_(table_unrefp) Table *t = NULL;
@@ -12,7 +36,7 @@ int main(int argc, char *argv[]) {
assert_se(setenv("COLUMNS", "40", 1) >= 0);
- assert_se(t = table_new("ONE", "TWO", "THREE"));
+ assert_se(t = table_new("one", "two", "three"));
assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(2), 100) >= 0);
@@ -135,5 +159,7 @@ int main(int argc, char *argv[]) {
" yes xxx yes xxx xxx \n"
"5min 5min \n"));
+ test_issue_9549();
+
return 0;
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index fc650b513e..b3a4b1749c 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -4,8 +4,6 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "id128-util.h"
#include "macro.h"
@@ -15,22 +13,35 @@
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
+#include "virt.h"
+
+static const char *arg_test_dir = NULL;
static void test_chase_symlinks(void) {
_cleanup_free_ char *result = NULL;
- char temp[] = "/tmp/test-chase.XXXXXX";
+ char *temp;
const char *top, *p, *pslash, *q, *qslash;
+ struct stat st;
int r, pfd;
+ log_info("/* %s */", __func__);
+
+ temp = strjoina(arg_test_dir ?: "/tmp", "/test-chase.XXXXXX");
assert_se(mkdtemp(temp));
top = strjoina(temp, "/top");
assert_se(mkdir(top, 0700) >= 0);
p = strjoina(top, "/dot");
- assert_se(symlink(".", p) >= 0);
+ if (symlink(".", p) < 0) {
+ assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
+ log_tests_skipped_errno(errno, "symlink() not possible");
+ goto cleanup;
+ };
p = strjoina(top, "/dotdot");
assert_se(symlink("..", p) >= 0);
@@ -237,11 +248,11 @@ static void test_chase_symlinks(void) {
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
assert_se(chown(q, 0, 0) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -EPERM);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
assert_se(rmdir(q) >= 0);
assert_se(symlink("/etc/passwd", q) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -EPERM);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
assert_se(chown(p, 0, 0) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
@@ -266,6 +277,30 @@ static void test_chase_symlinks(void) {
assert_se(sd_id128_equal(a, b));
}
+ /* Test CHASE_NOFOLLOW */
+
+ p = strjoina(temp, "/target");
+ q = strjoina(temp, "/symlink");
+ assert_se(symlink(p, q) >= 0);
+ pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
+ assert_se(pfd > 0);
+ assert_se(path_equal(result, q));
+ assert_se(fstat(pfd, &st) >= 0);
+ assert_se(S_ISLNK(st.st_mode));
+ result = mfree(result);
+
+ /* s1 -> s2 -> nonexistent */
+ q = strjoina(temp, "/s1");
+ assert_se(symlink("s2", q) >= 0);
+ p = strjoina(temp, "/s2");
+ assert_se(symlink("nonexistent", p) >= 0);
+ pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
+ assert_se(pfd > 0);
+ assert_se(path_equal(result, q));
+ assert_se(fstat(pfd, &st) >= 0);
+ assert_se(S_ISLNK(st.st_mode));
+ result = mfree(result);
+
/* Test CHASE_ONE */
p = strjoina(temp, "/start");
@@ -309,13 +344,17 @@ static void test_chase_symlinks(void) {
assert_se(streq("/usr", result));
result = mfree(result);
+ cleanup:
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
static void test_unlink_noerrno(void) {
- char name[] = "/tmp/test-close_nointr.XXXXXX";
+ char *name;
int fd;
+ log_info("/* %s */", __func__);
+
+ name = strjoina(arg_test_dir ?: "/tmp", "/test-close_nointr.XXXXXX");
fd = mkostemp_safe(name);
assert_se(fd >= 0);
assert_se(close_nointr(fd) >= 0);
@@ -331,32 +370,37 @@ static void test_unlink_noerrno(void) {
}
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;
- _cleanup_free_ char *pwd = NULL;
+ const char *tempdir, *name, *name2, *name_alias;
+ _cleanup_free_ char *r1 = NULL, *r2 = NULL, *pwd = NULL;
+
+ log_info("/* %s */", __func__);
+
+ tempdir = strjoina(arg_test_dir ?: "/tmp", "/test-readlink_and_make_absolute");
+ name = strjoina(tempdir, "/original");
+ name2 = "test-readlink_and_make_absolute/original";
+ name_alias = strjoina(arg_test_dir ?: "/tmp", "/test-readlink_and_make_absolute-alias");
assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 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);
+ if (symlink(name, name_alias) < 0) {
+ assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
+ log_tests_skipped_errno(errno, "symlink() not possible");
+ } else {
+ assert_se(readlink_and_make_absolute(name_alias, &r1) >= 0);
+ assert_se(streq(r1, name));
+ assert_se(unlink(name_alias) >= 0);
- assert_se(safe_getcwd(&pwd) >= 0);
+ assert_se(safe_getcwd(&pwd) >= 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(chdir(tempdir) >= 0);
+ assert_se(symlink(name2, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r2) >= 0);
+ assert_se(streq(r2, name));
+ assert_se(unlink(name_alias) >= 0);
- assert_se(chdir(pwd) >= 0);
+ assert_se(chdir(pwd) >= 0);
+ }
assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
@@ -364,7 +408,7 @@ static void test_readlink_and_make_absolute(void) {
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(arg_test_dir ?: "/tmp", &l) >= 0);
assert_se(get_files_in_directory(".", &t) >= 0);
assert_se(get_files_in_directory(".", NULL) >= 0);
}
@@ -373,6 +417,8 @@ static void test_var_tmp(void) {
_cleanup_free_ char *tmpdir_backup = NULL, *temp_backup = NULL, *tmp_backup = NULL;
const char *tmp_dir = NULL, *t;
+ log_info("/* %s */", __func__);
+
t = getenv("TMPDIR");
if (t) {
tmpdir_backup = strdup(t);
@@ -427,6 +473,8 @@ static void test_var_tmp(void) {
}
static void test_dot_or_dot_dot(void) {
+ log_info("/* %s */", __func__);
+
assert_se(!dot_or_dot_dot(NULL));
assert_se(!dot_or_dot_dot(""));
assert_se(!dot_or_dot_dot("xxx"));
@@ -439,8 +487,12 @@ static void test_dot_or_dot_dot(void) {
static void test_access_fd(void) {
_cleanup_(rmdir_and_freep) char *p = NULL;
_cleanup_close_ int fd = -1;
+ const char *a;
+
+ log_info("/* %s */", __func__);
- assert_se(mkdtemp_malloc("/tmp/access-fd.XXXXXX", &p) >= 0);
+ a = strjoina(arg_test_dir ?: "/tmp", "/access-fd.XXXXXX");
+ assert_se(mkdtemp_malloc(a, &p) >= 0);
fd = open(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
assert_se(fd >= 0);
@@ -468,16 +520,26 @@ static void test_touch_file(void) {
struct stat st;
const char *a;
usec_t test_mtime;
+ int r;
+
+ log_info("/* %s */", __func__);
test_uid = geteuid() == 0 ? 65534 : getuid();
test_gid = geteuid() == 0 ? 65534 : getgid();
test_mtime = usec_sub_unsigned(now(CLOCK_REALTIME), USEC_PER_WEEK);
- assert_se(mkdtemp_malloc("/dev/shm/touch-file-XXXXXX", &p) >= 0);
+ a = strjoina(arg_test_dir ?: "/dev/shm", "/touch-file-XXXXXX");
+ assert_se(mkdtemp_malloc(a, &p) >= 0);
a = strjoina(p, "/regular");
- assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ r = touch_file(a, false, test_mtime, test_uid, test_gid, 0640);
+ if (r < 0) {
+ assert_se(IN_SET(r, -EINVAL, -ENOSYS, -ENOTTY, -EPERM));
+ log_tests_skipped_errno(errno, "touch_file() not possible");
+ return;
+ }
+
assert_se(lstat(a, &st) >= 0);
assert_se(st.st_uid == test_uid);
assert_se(st.st_gid == test_gid);
@@ -517,7 +579,12 @@ static void test_touch_file(void) {
if (geteuid() == 0) {
a = strjoina(p, "/cdev");
- assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
+ r = mknod(a, 0775 | S_IFCHR, makedev(0, 0));
+ if (r < 0 && errno == EPERM && detect_container() > 0) {
+ log_notice("Running in unprivileged container? Skipping remaining tests in %s", __func__);
+ return;
+ }
+ assert_se(r >= 0);
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
assert_se(lstat(a, &st) >= 0);
assert_se(st.st_uid == test_uid);
@@ -553,7 +620,9 @@ static void test_unlinkat_deallocate(void) {
_cleanup_close_ int fd = -1;
struct stat st;
- assert_se(tempfn_random_child(NULL, "unlink-deallocation", &p) >= 0);
+ log_info("/* %s */", __func__);
+
+ assert_se(tempfn_random_child(arg_test_dir, "unlink-deallocation", &p) >= 0);
fd = open(p, O_WRONLY|O_CLOEXEC|O_CREAT|O_EXCL, 0600);
assert_se(fd >= 0);
@@ -568,7 +637,8 @@ static void test_unlinkat_deallocate(void) {
assert_se(unlinkat_deallocate(AT_FDCWD, p, 0) >= 0);
assert_se(fstat(fd, &st) >= 0);
- assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6 (it worked) or 0 (we had to resort to truncation) */
+ assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6
+ (it worked) or 0 (we had to resort to truncation) */
assert_se(st.st_blocks == 0);
assert_se(st.st_nlink == 0);
}
@@ -576,13 +646,87 @@ static void test_unlinkat_deallocate(void) {
static void test_fsync_directory_of_file(void) {
_cleanup_close_ int fd = -1;
- fd = open_tmpfile_unlinkable(NULL, O_RDWR);
+ log_info("/* %s */", __func__);
+
+ fd = open_tmpfile_unlinkable(arg_test_dir, O_RDWR);
assert_se(fd >= 0);
assert_se(fsync_directory_of_file(fd) >= 0);
}
+static void test_rename_noreplace(void) {
+ static const char* const table[] = {
+ "/reg",
+ "/dir",
+ "/fifo",
+ "/socket",
+ "/symlink",
+ NULL
+ };
+
+ _cleanup_(rm_rf_physical_and_freep) char *z = NULL;
+ const char *j = NULL;
+ char **a, **b;
+
+ log_info("/* %s */", __func__);
+
+ if (arg_test_dir)
+ j = strjoina(arg_test_dir, "/testXXXXXX");
+ assert_se(mkdtemp_malloc(j, &z) >= 0);
+
+ j = strjoina(z, table[0]);
+ assert_se(touch(j) >= 0);
+
+ j = strjoina(z, table[1]);
+ assert_se(mkdir(j, 0777) >= 0);
+
+ j = strjoina(z, table[2]);
+ (void) mkfifo(j, 0777);
+
+ j = strjoina(z, table[3]);
+ (void) mknod(j, S_IFSOCK | 0777, 0);
+
+ j = strjoina(z, table[4]);
+ (void) symlink("foobar", j);
+
+ STRV_FOREACH(a, (char**) table) {
+ _cleanup_free_ char *x = NULL, *y = NULL;
+
+ x = strjoin(z, *a);
+ assert_se(x);
+
+ if (access(x, F_OK) < 0) {
+ assert_se(errno == ENOENT);
+ continue;
+ }
+
+ STRV_FOREACH(b, (char**) table) {
+ _cleanup_free_ char *w = NULL;
+
+ w = strjoin(w, *b);
+ assert_se(w);
+
+ if (access(w, F_OK) < 0) {
+ assert_se(errno == ENOENT);
+ continue;
+ }
+
+ assert_se(rename_noreplace(AT_FDCWD, w, AT_FDCWD, y) == -EEXIST);
+ }
+
+ y = strjoin(z, "/somethingelse");
+ assert_se(y);
+
+ assert_se(rename_noreplace(AT_FDCWD, x, AT_FDCWD, y) >= 0);
+ assert_se(rename_noreplace(AT_FDCWD, y, AT_FDCWD, x) >= 0);
+ }
+}
+
int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ arg_test_dir = argv[1];
+
test_unlink_noerrno();
test_get_files_in_directory();
test_readlink_and_make_absolute();
@@ -593,6 +737,7 @@ int main(int argc, char *argv[]) {
test_touch_file();
test_unlinkat_deallocate();
test_fsync_directory_of_file();
+ test_rename_noreplace();
return 0;
}
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
index d78d6223c0..b4f41445fe 100644
--- a/src/test/test-glob-util.c
+++ b/src/test/test-glob-util.c
@@ -7,11 +7,11 @@
#include "alloc-util.h"
#include "dirent-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "glob-util.h"
#include "macro.h"
#include "rm-rf.h"
+#include "tmpfile-util.h"
static void test_glob_exists(void) {
char name[] = "/tmp/test-glob_exists.XXXXXX";
diff --git a/src/test/test-hash.c b/src/test/test-hash.c
index f5bc131846..44d1044bf3 100644
--- a/src/test/test-hash.c
+++ b/src/test/test-hash.c
@@ -7,23 +7,22 @@
#include "log.h"
#include "string-util.h"
#include "khash.h"
+#include "tests.h"
int main(int argc, char *argv[]) {
_cleanup_(khash_unrefp) khash *h = NULL, *copy = NULL;
_cleanup_free_ char *s = NULL;
int r;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
assert_se(khash_new(&h, NULL) == -EINVAL);
assert_se(khash_new(&h, "") == -EINVAL);
r = khash_supported();
assert_se(r >= 0);
- if (r == 0) {
- puts("khash not supported on this kernel, skipping");
- return EXIT_TEST_SKIP;
- }
+ if (r == 0)
+ return log_tests_skipped("khash not supported on this kernel");
assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP); /* undefined hash function */
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index b695d4ee35..5376aa84c4 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -1,25 +1,21 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Daniel Buch
-***/
#include "alloc-util.h"
-#include "env-util.h"
#include "hashmap.h"
#include "log.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
#include "util.h"
-static bool arg_slow = false;
-
void test_hashmap_funcs(void);
static void test_hashmap_replace(void) {
Hashmap *m;
char *val1, *val2, *val3, *val4, *val5, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
@@ -59,7 +55,7 @@ static void test_hashmap_copy(void) {
Hashmap *m, *copy;
char *val1, *val2, *val3, *val4, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("val1");
assert_se(val1);
@@ -97,7 +93,7 @@ static void test_hashmap_get_strv(void) {
char **strv;
char *val1, *val2, *val3, *val4;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("val1");
assert_se(val1);
@@ -135,7 +131,7 @@ static void test_hashmap_move_one(void) {
Hashmap *m, *n;
char *val1, *val2, *val3, *val4, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("val1");
assert_se(val1);
@@ -176,7 +172,7 @@ static void test_hashmap_move(void) {
Hashmap *m, *n;
char *val1, *val2, *val3, *val4, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("val1");
assert_se(val1);
@@ -220,7 +216,7 @@ static void test_hashmap_update(void) {
Hashmap *m;
char *val1, *val2, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
val1 = strdup("old_value");
@@ -252,7 +248,7 @@ static void test_hashmap_put(void) {
void *val2 = (void*) "val 2";
_cleanup_free_ char* key1 = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0);
assert_se(m);
@@ -272,7 +268,7 @@ static void test_hashmap_remove(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
char *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
r = hashmap_remove(NULL, "key 1");
assert_se(r == NULL);
@@ -302,7 +298,7 @@ static void test_hashmap_remove2(void) {
char val2[] = "val 2";
void *r, *r2;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
r = hashmap_remove2(NULL, "key 1", &r2);
assert_se(r == NULL);
@@ -334,7 +330,7 @@ static void test_hashmap_remove_value(void) {
char val1[] = "val 1";
char val2[] = "val 2";
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
r = hashmap_remove_value(NULL, "key 1", val1);
assert_se(r == NULL);
@@ -368,7 +364,7 @@ static void test_hashmap_remove_and_put(void) {
int valid;
char *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -404,7 +400,7 @@ static void test_hashmap_remove_and_replace(void) {
void *r;
int i, j;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&trivial_hash_ops);
assert_se(m);
@@ -457,7 +453,7 @@ static void test_hashmap_ensure_allocated(void) {
Hashmap *m;
int valid_hashmap;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
@@ -480,7 +476,7 @@ static void test_hashmap_foreach_key(void) {
"key 3\0"
"key 4\0";
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
@@ -512,7 +508,7 @@ static void test_hashmap_foreach(void) {
char *val1, *val2, *val3, *val4, *s;
unsigned count;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("my val1");
assert_se(val1);
@@ -564,7 +560,7 @@ static void test_hashmap_merge(void) {
Hashmap *n;
char *val1, *val2, *val3, *val4, *r;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("my val1");
assert_se(val1);
@@ -599,7 +595,7 @@ static void test_hashmap_contains(void) {
Hashmap *m;
char *val1;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("my val");
assert_se(val1);
@@ -621,7 +617,7 @@ static void test_hashmap_isempty(void) {
Hashmap *m;
char *val1;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("my val");
assert_se(val1);
@@ -640,7 +636,7 @@ static void test_hashmap_size(void) {
Hashmap *m;
char *val1, *val2, *val3, *val4;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val1 = strdup("my val");
assert_se(val1);
@@ -672,7 +668,7 @@ static void test_hashmap_get(void) {
char *r;
char *val;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val = strdup("my val");
assert_se(val);
@@ -701,7 +697,7 @@ static void test_hashmap_get2(void) {
char key_orig[] = "Key 1";
void *key_copy;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
val = strdup("my val");
assert_se(val);
@@ -742,17 +738,22 @@ static void test_hashmap_many(void) {
Hashmap *h;
unsigned i, j;
void *v, *k;
+ bool slow = slow_tests_enabled();
const struct {
+ const char *title;
const struct hash_ops *ops;
unsigned n_entries;
} tests[] = {
- { .ops = NULL, .n_entries = arg_slow ? 1 << 20 : 240 },
- { .ops = &crippled_hashmap_ops, .n_entries = arg_slow ? 1 << 14 : 140 },
+ { "trivial_hashmap_ops", NULL, slow ? 1 << 20 : 240 },
+ { "crippled_hashmap_ops", &crippled_hashmap_ops, slow ? 1 << 14 : 140 },
};
- log_info("%s (%s)", __func__, arg_slow ? "slow" : "fast");
+ log_info("/* %s (%s) */", __func__, slow ? "slow" : "fast");
for (j = 0; j < ELEMENTSOF(tests); j++) {
+ usec_t ts = now(CLOCK_MONOTONIC), n;
+ char b[FORMAT_TIMESPAN_MAX];
+
assert_se(h = hashmap_new(tests[j].ops));
for (i = 1; i < tests[j].n_entries*3; i+=3) {
@@ -763,7 +764,8 @@ static void test_hashmap_many(void) {
for (i = 1; i < tests[j].n_entries*3; i++)
assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1));
- log_info("%u <= %u * 0.8 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8);
+ log_info("%s %u <= %u * 0.8 = %g",
+ tests[j].title, hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8);
assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.8);
assert_se(hashmap_size(h) == tests[j].n_entries);
@@ -775,13 +777,63 @@ static void test_hashmap_many(void) {
}
hashmap_free(h);
+
+ n = now(CLOCK_MONOTONIC);
+ log_info("test took %s", format_timespan(b, sizeof b, n - ts, 0));
+ }
+}
+
+extern unsigned custom_counter;
+extern const struct hash_ops boring_hash_ops, custom_hash_ops;
+
+static void test_hashmap_free(void) {
+ Hashmap *h;
+ bool slow = slow_tests_enabled();
+ usec_t ts, n;
+ char b[FORMAT_TIMESPAN_MAX];
+ unsigned n_entries = slow ? 1 << 20 : 240;
+
+ const struct {
+ const char *title;
+ const struct hash_ops *ops;
+ unsigned expect_counter;
+ } tests[] = {
+ { "string_hash_ops", &boring_hash_ops, 2 * n_entries},
+ { "custom_free_hash_ops", &custom_hash_ops, 0 },
+ };
+
+ log_info("/* %s (%s, %u entries) */", __func__, slow ? "slow" : "fast", n_entries);
+
+ for (unsigned j = 0; j < ELEMENTSOF(tests); j++) {
+ ts = now(CLOCK_MONOTONIC);
+ assert_se(h = hashmap_new(tests[j].ops));
+
+ custom_counter = 0;
+ for (unsigned i = 0; i < n_entries; i++) {
+ char s[DECIMAL_STR_MAX(unsigned)];
+ char *k, *v;
+
+ xsprintf(s, "%u", i);
+ assert_se(k = strdup(s));
+ assert_se(v = strdup(s));
+ custom_counter += 2;
+
+ assert_se(hashmap_put(h, k, v) >= 0);
+ }
+
+ hashmap_free(h);
+
+ n = now(CLOCK_MONOTONIC);
+ log_info("%s test took %s", tests[j].title, format_timespan(b, sizeof b, n - ts, 0));
+
+ assert_se(custom_counter == tests[j].expect_counter);
}
}
static void test_hashmap_first(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -800,7 +852,7 @@ static void test_hashmap_first(void) {
static void test_hashmap_first_key(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -819,7 +871,7 @@ static void test_hashmap_first_key(void) {
static void test_hashmap_steal_first_key(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -836,7 +888,7 @@ static void test_hashmap_steal_first(void) {
int seen[3] = {};
char *val;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -856,7 +908,7 @@ static void test_hashmap_steal_first(void) {
static void test_hashmap_clear_free_free(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -867,12 +919,49 @@ static void test_hashmap_clear_free_free(void) {
hashmap_clear_free_free(m);
assert_se(hashmap_isempty(m));
+
+ assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1);
+ assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1);
+ assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1);
+
+ hashmap_clear_free_free(m);
+ assert_se(hashmap_isempty(m));
+}
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(test_hash_ops_key, char, string_hash_func, string_compare_func, free);
+DEFINE_PRIVATE_HASH_OPS_FULL(test_hash_ops_full, char, string_hash_func, string_compare_func, free, char, free);
+
+static void test_hashmap_clear_free_with_destructor(void) {
+ _cleanup_hashmap_free_ Hashmap *m = NULL;
+
+ log_info("/* %s */", __func__);
+
+ m = hashmap_new(&test_hash_ops_key);
+ assert_se(m);
+
+ assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1);
+ assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1);
+ assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1);
+
+ hashmap_clear_free(m);
+ assert_se(hashmap_isempty(m));
+ m = hashmap_free(m);
+
+ m = hashmap_new(&test_hash_ops_full);
+ assert_se(m);
+
+ assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1);
+ assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1);
+ assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1);
+
+ hashmap_clear_free(m);
+ assert_se(hashmap_isempty(m));
}
static void test_hashmap_reserve(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
- log_info("%s", __func__);
+ log_info("/* %s */", __func__);
m = hashmap_new(&string_hash_ops);
@@ -889,14 +978,9 @@ static void test_hashmap_reserve(void) {
}
void test_hashmap_funcs(void) {
- int r;
-
log_parse_environment();
log_open();
- r = getenv_bool("SYSTEMD_SLOW_TESTS");
- arg_slow = r >= 0 ? r : SYSTEMD_SLOW_TESTS_DEFAULT;
-
test_hashmap_copy();
test_hashmap_get_strv();
test_hashmap_move_one();
@@ -919,10 +1003,12 @@ void test_hashmap_funcs(void) {
test_hashmap_get2();
test_hashmap_size();
test_hashmap_many();
+ test_hashmap_free();
test_hashmap_first();
test_hashmap_first_key();
test_hashmap_steal_first_key();
test_hashmap_steal_first();
test_hashmap_clear_free_free();
+ test_hashmap_clear_free_with_destructor();
test_hashmap_reserve();
}
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index b319fa6ba9..ee4c0e66db 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -1,11 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Daniel Buch
-***/
#include "hashmap.h"
#include "util.h"
+unsigned custom_counter = 0;
+static void custom_destruct(void* p) {
+ custom_counter--;
+ free(p);
+}
+
+DEFINE_HASH_OPS_FULL(boring_hash_ops, char, string_hash_func, string_compare_func, free, char, free);
+DEFINE_HASH_OPS_FULL(custom_hash_ops, char, string_hash_func, string_compare_func, custom_destruct, char, custom_destruct);
+
void test_hashmap_funcs(void);
void test_ordered_hashmap_funcs(void);
@@ -13,6 +19,8 @@ static void test_ordered_hashmap_next(void) {
_cleanup_ordered_hashmap_free_ OrderedHashmap *m = NULL;
int i;
+ log_info("/* %s */", __func__);
+
assert_se(m = ordered_hashmap_new(NULL));
for (i = -2; i <= 2; i++)
assert_se(ordered_hashmap_put(m, INT_TO_PTR(i), INT_TO_PTR(i+10)) == 1);
@@ -35,6 +43,8 @@ static void test_hashmap_free_with_destructor(void) {
struct Item items[4] = {};
unsigned i;
+ log_info("/* %s */", __func__);
+
assert_se(m = hashmap_new(NULL));
for (i = 0; i < ELEMENTSOF(items) - 1; i++)
assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1);
@@ -90,6 +100,8 @@ static void test_iterated_cache(void) {
Hashmap *m;
IteratedCache *c;
+ log_info("/* %s */", __func__);
+
assert_se(m = hashmap_new(NULL));
assert_se(c = hashmap_iterated_cache_new(m));
compare_cache(m, c);
@@ -125,6 +137,8 @@ static void test_iterated_cache(void) {
static void test_path_hashmap(void) {
_cleanup_hashmap_free_ Hashmap *h = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(h = hashmap_new(&path_hash_ops));
assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0);
diff --git a/src/test/test-helper.c b/src/test/test-helper.c
index 9cf9972380..5b79d12f07 100644
--- a/src/test/test-helper.c
+++ b/src/test/test-helper.c
@@ -4,6 +4,7 @@
#include "random-util.h"
#include "alloc-util.h"
#include "cgroup-util.h"
+#include "string-util.h"
int enter_cgroup_subroot(void) {
_cleanup_free_ char *cgroup_root = NULL, *cgroup_subroot = NULL;
@@ -27,3 +28,8 @@ int enter_cgroup_subroot(void) {
return cg_attach_everywhere(supported, cgroup_subroot, 0, NULL, NULL);
}
+
+/* https://docs.travis-ci.com/user/environment-variables#default-environment-variables */
+bool is_run_on_travis_ci(void) {
+ return streq_ptr(getenv("TRAVIS"), "true");
+}
diff --git a/src/test/test-helper.h b/src/test/test-helper.h
index 3e8ccd9049..77af40d555 100644
--- a/src/test/test-helper.h
+++ b/src/test/test-helper.h
@@ -27,3 +27,5 @@
)
int enter_cgroup_subroot(void);
+
+bool is_run_on_travis_ci(void);
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
index da9f3008bb..6e9b94b933 100644
--- a/src/test/test-hexdecoct.c
+++ b/src/test/test-hexdecoct.c
@@ -84,7 +84,7 @@ static void test_unhexmem_one(const char *s, size_t l, int retval) {
l = strlen(s);
assert_se(hex = hexmem(mem, len));
- answer = strndupa(s, l);
+ answer = strndupa(strempty(s), l);
assert_se(streq(delete_chars(answer, WHITESPACE), hex));
}
}
diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c
index 194a640eee..4126a24ceb 100644
--- a/src/test/test-hostname-util.c
+++ b/src/test/test-hostname-util.c
@@ -4,6 +4,7 @@
#include "fileio.h"
#include "hostname-util.h"
#include "string-util.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_hostname_is_valid(void) {
@@ -52,6 +53,12 @@ static void test_hostname_cleanup(void) {
assert_se(streq(hostname_cleanup(s), "foobar.com"));
s = strdupa("foobar.com.");
assert_se(streq(hostname_cleanup(s), "foobar.com"));
+ s = strdupa("foo-bar.-com-.");
+ assert_se(streq(hostname_cleanup(s), "foo-bar.com"));
+ s = strdupa("foo-bar-.-com-.");
+ assert_se(streq(hostname_cleanup(s), "foo-bar--com"));
+ s = strdupa("--foo-bar.-com");
+ assert_se(streq(hostname_cleanup(s), "foo-bar.com"));
s = strdupa("fooBAR");
assert_se(streq(hostname_cleanup(s), "fooBAR"));
s = strdupa("fooBAR.com");
@@ -78,6 +85,8 @@ static void test_hostname_cleanup(void) {
assert_se(streq(hostname_cleanup(s), "foo.bar"));
s = strdupa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
assert_se(streq(hostname_cleanup(s), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
+ s = strdupa("xxxx........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+ assert_se(streq(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
}
static void test_read_etc_hostname(void) {
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index e3d07a69f3..ec50e057a3 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -7,10 +7,10 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "id128-util.h"
#include "macro.h"
#include "string-util.h"
+#include "tmpfile-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)
diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c
index 5b6e87bf5a..75c3e305c3 100644
--- a/src/test/test-in-addr-util.c
+++ b/src/test/test-in-addr-util.c
@@ -4,12 +4,12 @@
#include "in-addr-util.h"
-static void test_in_addr_prefix_from_string(const char *p, int family, int ret, const union in_addr_union *u, unsigned char prefixlen) {
+static void test_in_addr_prefix_from_string(const char *p, int family, int ret, const union in_addr_union *u, unsigned char prefixlen, bool use_default) {
union in_addr_union q;
unsigned char l;
int r;
- r = in_addr_prefix_from_string(p, family, &q, &l);
+ r = in_addr_prefix_from_string_internal(p, use_default, family, &q, &l);
assert_se(r == ret);
if (r >= 0) {
@@ -18,7 +18,7 @@ static void test_in_addr_prefix_from_string(const char *p, int family, int ret,
assert_se(in_addr_equal(family, &q, u));
assert_se(l == prefixlen);
- r = in_addr_prefix_from_string_auto(p, &f, &q, &l);
+ r = in_addr_prefix_from_string_auto_internal(p, use_default, &f, &q, &l);
assert_se(r >= 0);
assert_se(f == family);
@@ -28,31 +28,57 @@ static void test_in_addr_prefix_from_string(const char *p, int family, int ret,
}
int main(int argc, char *argv[]) {
- test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32);
- test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0);
- test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1);
- test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2);
- test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32);
- test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0);
-
- test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128);
- test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0);
- test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1);
- test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2);
- test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32);
- test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33);
- test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64);
- test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128);
- test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0);
+ test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
+ test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, false);
+ test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, false);
+ test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
+ test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, false);
+
+ test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
+ test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, false);
+ test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, false);
+ test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, false);
+ test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, false);
+ test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, false);
+ test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, false);
+ test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
+ test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, false);
+
+ test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 8, true);
+ test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, true);
+ test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, true);
+ test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, true);
+ test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, true);
+
+ test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
+ test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
+ test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, true);
+ test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, true);
+ test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, true);
+ test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, true);
+ test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, true);
+ test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, true);
+ test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, true);
return 0;
}
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index 15dd3c6966..73ea68f372 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -7,6 +7,7 @@
#include "rm-rf.h"
#include "special.h"
#include "string-util.h"
+#include "tests.h"
static void test_basic_mask_and_enable(const char *root) {
const char *p;
@@ -14,7 +15,7 @@ static void test_basic_mask_and_enable(const char *root) {
UnitFileChange *changes = NULL;
size_t n_changes = 0;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(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);
@@ -861,7 +862,7 @@ static void test_with_dropin(const char *root) {
unit_file_changes_free(changes, n_changes);
changes = NULL; n_changes = 0;
- assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 1);
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 2);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
assert_se(n_changes == 2);
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
@@ -983,6 +984,63 @@ static void test_with_dropin_template(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
}
+static void test_preset_multiple_instances(const char *root) {
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0;
+ const char *p;
+ UnitFileState state;
+
+ /* Set up template service files and preset file */
+ p = strjoina(root, "/usr/lib/systemd/system/foo@.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "DefaultInstance=def\n"
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
+ assert_se(write_string_file(p,
+ "enable foo@.service bar0 bar1 bartest\n"
+ "enable emptylist@.service\n" /* This line ensures the old functionality for templated unit still works */
+ "disable *\n" , WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ /* Preset a single instantiated unit specified in the list */
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(n_changes == 1);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.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/foo@bar0.service");
+ assert_se(streq(changes[0].path, p));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ /* Check for preset-all case, only instances on the list should be enabled, not including the default instance */
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
+ assert_se(n_changes > 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ unit_file_changes_free(changes, n_changes);
+}
+
int main(int argc, char *argv[]) {
char root[] = "/tmp/rootXXXXXX";
const char *p;
@@ -1012,6 +1070,7 @@ int main(int argc, char *argv[]) {
test_indirect(root);
test_preset_and_list(root);
test_preset_order(root);
+ test_preset_multiple_instances(root);
test_revert(root);
test_static_instance(root);
test_with_dropin(root);
diff --git a/src/test/test-install.c b/src/test/test-install.c
index 7dfc7e4272..62daaccd62 100644
--- a/src/test/test-install.c
+++ b/src/test/test-install.c
@@ -4,6 +4,7 @@
#include <string.h>
#include "install.h"
+#include "tests.h"
static void dump_changes(UnitFileChange *c, unsigned n) {
unsigned i;
@@ -29,8 +30,7 @@ int main(int argc, char* argv[]) {
size_t n_changes = 0;
UnitFileState state = 0;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
h = hashmap_new(&string_hash_ops);
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
diff --git a/src/test/test-ip-protocol-list.c b/src/test/test-ip-protocol-list.c
new file mode 100644
index 0000000000..79390e5289
--- /dev/null
+++ b/src/test/test-ip-protocol-list.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <netinet/in.h>
+
+#include "macro.h"
+#include "ip-protocol-list.h"
+#include "stdio-util.h"
+#include "string-util.h"
+
+static void test_int(int i) {
+ char str[DECIMAL_STR_MAX(int)];
+
+ assert_se(ip_protocol_from_name(ip_protocol_to_name(i)) == i);
+
+ xsprintf(str, "%i", i);
+ assert_se(ip_protocol_from_name(ip_protocol_to_name(parse_ip_protocol(str))) == i);
+}
+
+static void test_int_fail(int i) {
+ char str[DECIMAL_STR_MAX(int)];
+
+ assert_se(!ip_protocol_to_name(i));
+
+ xsprintf(str, "%i", i);
+ assert_se(parse_ip_protocol(str) == -EINVAL);
+}
+
+static void test_str(const char *s) {
+ assert_se(streq(ip_protocol_to_name(ip_protocol_from_name(s)), s));
+ assert_se(streq(ip_protocol_to_name(parse_ip_protocol(s)), s));
+}
+
+static void test_str_fail(const char *s) {
+ assert_se(ip_protocol_from_name(s) == -EINVAL);
+ assert_se(parse_ip_protocol(s) == -EINVAL);
+}
+
+static void test_parse_ip_protocol(const char *s, int expected) {
+ assert_se(parse_ip_protocol(s) == expected);
+}
+
+int main(int argc, const char *argv[]) {
+ test_int(IPPROTO_TCP);
+ test_int(IPPROTO_DCCP);
+ test_int_fail(-1);
+ test_int_fail(1024 * 1024);
+
+ test_str("sctp");
+ test_str("udp");
+ test_str_fail("hoge");
+ test_str_fail("-1");
+ test_str_fail("1000000000");
+
+ test_parse_ip_protocol("sctp", IPPROTO_SCTP);
+ test_parse_ip_protocol("ScTp", IPPROTO_SCTP);
+ test_parse_ip_protocol("ip", IPPROTO_IP);
+ test_parse_ip_protocol("", IPPROTO_IP);
+ test_parse_ip_protocol("1", 1);
+ test_parse_ip_protocol("0", 0);
+ test_parse_ip_protocol("-10", -EINVAL);
+ test_parse_ip_protocol("100000000", -EINVAL);
+
+ return 0;
+}
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 106c29951e..4b658a0bdb 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -2,6 +2,7 @@
#include "clean-ipc.h"
#include "user-util.h"
+#include "tests.h"
#include "util.h"
int main(int argc, char *argv[]) {
@@ -9,11 +10,14 @@ int main(int argc, char *argv[]) {
int r;
const char* name = argv[1] ?: NOBODY_USER_NAME;
- r = get_user_creds(&name, &uid, NULL, NULL, NULL);
+ test_setup_logging(LOG_INFO);
+
+ r = get_user_creds(&name, &uid, NULL, NULL, NULL, 0);
+ if (r == -ESRCH)
+ return log_tests_skipped("Failed to resolve user");
if (r < 0) {
- log_full_errno(r == -ESRCH ? LOG_NOTICE : LOG_ERR,
- r, "Failed to resolve \"%s\": %m", name);
- return r == -ESRCH ? EXIT_TEST_SKIP : EXIT_FAILURE;
+ log_error_errno(r, "Failed to resolve \"%s\": %m", name);
+ return EXIT_FAILURE;
}
r = clean_ipc_by_uid(uid);
diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c
index dc5f9eae83..d51e0d94fd 100644
--- a/src/test/test-job-type.c
+++ b/src/test/test-job-type.c
@@ -6,7 +6,7 @@
#include "service.h"
#include "unit.h"
-int main(int argc, char*argv[]) {
+int main(int argc, char *argv[]) {
JobType a, b, c, ab, bc, ab_c, bc_a, a_bc;
const ServiceState test_states[] = { SERVICE_DEAD, SERVICE_RUNNING };
unsigned i;
diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c
index 56bf6a1296..cddbfa7022 100644
--- a/src/test/test-journal-importer.c
+++ b/src/test/test-journal-importer.c
@@ -4,8 +4,10 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include "alloc-util.h"
#include "log.h"
#include "journal-importer.h"
+#include "path-util.h"
#include "string-util.h"
#include "tests.h"
@@ -20,9 +22,11 @@ static void assert_iovec_entry(const struct iovec *iovec, const char* content) {
static void test_basic_parsing(void) {
_cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ _cleanup_free_ char *journal_data_path = NULL;
int r;
- imp.fd = open(get_testdata_dir("/journal-data/journal-1.txt"), O_RDONLY|O_CLOEXEC);
+ journal_data_path = path_join(get_testdata_dir(), "journal-data/journal-1.txt");
+ imp.fd = open(journal_data_path, O_RDONLY|O_CLOEXEC);
assert_se(imp.fd >= 0);
do
@@ -49,9 +53,11 @@ static void test_basic_parsing(void) {
static void test_bad_input(void) {
_cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ _cleanup_free_ char *journal_data_path = NULL;
int r;
- imp.fd = open(get_testdata_dir("/journal-data/journal-2.txt"), O_RDONLY|O_CLOEXEC);
+ journal_data_path = path_join(get_testdata_dir(), "journal-data/journal-2.txt");
+ imp.fd = open(journal_data_path, O_RDONLY|O_CLOEXEC);
assert_se(imp.fd >= 0);
do
@@ -63,8 +69,7 @@ static void test_bad_input(void) {
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
test_basic_parsing();
test_bad_input();
diff --git a/src/test/test-json.c b/src/test/test-json.c
new file mode 100644
index 0000000000..5aa4d19dbe
--- /dev/null
+++ b/src/test/test-json.c
@@ -0,0 +1,462 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <math.h>
+#if HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "json-internal.h"
+#include "json.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+static void test_tokenizer(const char *data, ...) {
+ unsigned line = 0, column = 0;
+ void *state = NULL;
+ va_list ap;
+
+ va_start(ap, data);
+
+ for (;;) {
+ unsigned token_line, token_column;
+ _cleanup_free_ char *str = NULL;
+ JsonValue v = JSON_VALUE_NULL;
+ int t, tt;
+
+ t = json_tokenize(&data, &str, &v, &token_line, &token_column, &state, &line, &column);
+ tt = va_arg(ap, int);
+
+ assert_se(t == tt);
+
+ if (t == JSON_TOKEN_END || t < 0)
+ break;
+
+ else if (t == JSON_TOKEN_STRING) {
+ const char *nn;
+
+ nn = va_arg(ap, const char *);
+ assert_se(streq_ptr(nn, str));
+
+ } else if (t == JSON_TOKEN_REAL) {
+ long double d;
+
+ d = va_arg(ap, long double);
+
+#if HAVE_VALGRIND_VALGRIND_H
+ if (!RUNNING_ON_VALGRIND)
+#endif
+ /* Valgrind doesn't support long double calculations and automatically downgrades to 80bit:
+ * http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits */
+ assert_se(fabsl(d - v.real) < 0.001L);
+
+ } else if (t == JSON_TOKEN_INTEGER) {
+ intmax_t i;
+
+ i = va_arg(ap, intmax_t);
+ assert_se(i == v.integer);
+
+ } else if (t == JSON_TOKEN_UNSIGNED) {
+ uintmax_t u;
+
+ u = va_arg(ap, uintmax_t);
+ assert_se(u == v.unsig);
+
+ } else if (t == JSON_TOKEN_BOOLEAN) {
+ bool b;
+
+ b = va_arg(ap, int);
+ assert_se(b == v.boolean);
+ }
+ }
+
+ va_end(ap);
+}
+
+typedef void (*Test)(JsonVariant *);
+
+static void test_variant(const char *data, Test test) {
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
+ _cleanup_free_ char *s = NULL;
+ int r;
+
+ r = json_parse(data, &v, NULL, NULL);
+ assert_se(r == 0);
+ assert_se(v);
+
+ r = json_variant_format(v, 0, &s);
+ assert_se(r >= 0);
+ assert_se(s);
+
+ log_info("formatted normally: %s\n", s);
+
+ r = json_parse(data, &w, NULL, NULL);
+ assert_se(r == 0);
+ assert_se(w);
+ assert_se(json_variant_has_type(v, json_variant_type(w)));
+ assert_se(json_variant_has_type(w, json_variant_type(v)));
+ assert_se(json_variant_equal(v, w));
+
+ s = mfree(s);
+ w = json_variant_unref(w);
+
+ r = json_variant_format(v, JSON_FORMAT_PRETTY, &s);
+ assert_se(r >= 0);
+ assert_se(s);
+
+ log_info("formatted prettily:\n%s", s);
+
+ r = json_parse(data, &w, NULL, NULL);
+ assert_se(r == 0);
+ assert_se(w);
+
+ assert_se(json_variant_has_type(v, json_variant_type(w)));
+ assert_se(json_variant_has_type(w, json_variant_type(v)));
+ assert_se(json_variant_equal(v, w));
+
+ s = mfree(s);
+ r = json_variant_format(v, JSON_FORMAT_COLOR, &s);
+ assert_se(r >= 0);
+ assert_se(s);
+ printf("Normal with color: %s\n", s);
+
+ s = mfree(s);
+ r = json_variant_format(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, &s);
+ assert_se(r >= 0);
+ assert_se(s);
+ printf("Pretty with color:\n%s\n", s);
+
+ if (test)
+ test(v);
+}
+
+static void test_1(JsonVariant *v) {
+ JsonVariant *p, *q;
+ unsigned i;
+
+ /* 3 keys + 3 values */
+ assert_se(json_variant_elements(v) == 6);
+
+ /* has k */
+ p = json_variant_by_key(v, "k");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_STRING);
+
+ /* k equals v */
+ assert_se(streq(json_variant_string(p), "v"));
+
+ /* has foo */
+ p = json_variant_by_key(v, "foo");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 3);
+
+ /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */
+ for (i = 0; i < 3; ++i) {
+ q = json_variant_by_index(p, i);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == (i+1));
+ assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == (i+1));
+ }
+
+ /* has bar */
+ p = json_variant_by_key(v, "bar");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_OBJECT && json_variant_elements(p) == 2);
+
+ /* zap is null */
+ q = json_variant_by_key(p, "zap");
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_NULL);
+}
+
+static void test_2(JsonVariant *v) {
+ JsonVariant *p, *q;
+
+ /* 2 keys + 2 values */
+ assert_se(json_variant_elements(v) == 4);
+
+ /* has mutant */
+ p = json_variant_by_key(v, "mutant");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 4);
+
+ /* mutant[0] == 1 */
+ q = json_variant_by_index(p, 0);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == 1);
+ assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == 1);
+
+ /* mutant[1] == null */
+ q = json_variant_by_index(p, 1);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_NULL);
+
+ /* mutant[2] == "1" */
+ q = json_variant_by_index(p, 2);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
+
+ /* mutant[3] == JSON_VARIANT_OBJECT */
+ q = json_variant_by_index(p, 3);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_OBJECT && json_variant_elements(q) == 2);
+
+ /* has 1 */
+ p = json_variant_by_key(q, "1");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 2);
+
+ /* "1"[0] == 1 */
+ q = json_variant_by_index(p, 0);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == 1);
+ assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == 1);
+
+ /* "1"[1] == "1" */
+ q = json_variant_by_index(p, 1);
+ assert_se(q && json_variant_type(q) == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
+
+ /* has thisisaverylongproperty */
+ p = json_variant_by_key(v, "thisisaverylongproperty");
+ assert_se(p && json_variant_type(p) == JSON_VARIANT_REAL && fabsl(json_variant_real(p) - 1.27) < 0.001);
+}
+
+
+static void test_zeroes(JsonVariant *v) {
+ size_t i;
+
+ /* Make sure zero is how we expect it. */
+
+ assert_se(json_variant_elements(v) == 13);
+
+ for (i = 0; i < json_variant_elements(v); i++) {
+ JsonVariant *w;
+ size_t j;
+
+ assert_se(w = json_variant_by_index(v, i));
+
+ assert_se(json_variant_integer(w) == 0);
+ assert_se(json_variant_unsigned(w) == 0U);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+ assert_se(json_variant_real(w) == 0.0L);
+#pragma GCC diagnostic pop
+
+ assert_se(json_variant_is_integer(w));
+ assert_se(json_variant_is_unsigned(w));
+ assert_se(json_variant_is_real(w));
+ assert_se(json_variant_is_number(w));
+
+ assert_se(!json_variant_is_negative(w));
+
+ assert_se(IN_SET(json_variant_type(w), JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL));
+
+ for (j = 0; j < json_variant_elements(v); j++) {
+ JsonVariant *q;
+
+ assert_se(q = json_variant_by_index(v, j));
+
+ assert_se(json_variant_equal(w, q));
+ }
+ }
+}
+
+static void test_build(void) {
+ _cleanup_(json_variant_unrefp) JsonVariant *a = NULL, *b = NULL;
+ _cleanup_free_ char *s = NULL, *t = NULL;
+
+ assert_se(json_build(&a, JSON_BUILD_STRING("hallo")) >= 0);
+ assert_se(json_build(&b, JSON_BUILD_LITERAL(" \"hallo\" ")) >= 0);
+ assert_se(json_variant_equal(a, b));
+
+ b = json_variant_unref(b);
+
+ assert_se(json_build(&b, JSON_BUILD_VARIANT(a)) >= 0);
+ assert_se(json_variant_equal(a, b));
+
+ b = json_variant_unref(b);
+ assert_se(json_build(&b, JSON_BUILD_STRING("pief")) >= 0);
+ assert_se(!json_variant_equal(a, b));
+
+ a = json_variant_unref(a);
+ b = json_variant_unref(b);
+
+ assert_se(json_build(&a, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("one", JSON_BUILD_INTEGER(7)),
+ JSON_BUILD_PAIR("two", JSON_BUILD_REAL(2.0)),
+ JSON_BUILD_PAIR("three", JSON_BUILD_INTEGER(0)))) >= 0);
+
+ assert_se(json_build(&b, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("two", JSON_BUILD_INTEGER(2)),
+ JSON_BUILD_PAIR("three", JSON_BUILD_REAL(0)),
+ JSON_BUILD_PAIR("one", JSON_BUILD_REAL(7)))) >= 0);
+
+ assert_se(json_variant_equal(a, b));
+
+ a = json_variant_unref(a);
+ b = json_variant_unref(b);
+
+ assert_se(json_build(&a, JSON_BUILD_ARRAY(JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_BOOLEAN(true)),
+ JSON_BUILD_PAIR("y", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("this", JSON_BUILD_NULL)))),
+ JSON_BUILD_VARIANT(NULL),
+ JSON_BUILD_LITERAL(NULL),
+ JSON_BUILD_STRING(NULL),
+ JSON_BUILD_NULL,
+ JSON_BUILD_INTEGER(77),
+ JSON_BUILD_ARRAY(JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")), JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))),
+ JSON_BUILD_STRV(STRV_MAKE("one", "two", "three", "four")))) >= 0);
+
+ assert_se(json_variant_format(a, 0, &s) >= 0);
+ log_info("GOT: %s\n", s);
+ assert_se(json_parse(s, &b, NULL, NULL) >= 0);
+ assert_se(json_variant_equal(a, b));
+
+ a = json_variant_unref(a);
+ b = json_variant_unref(b);
+
+ assert_se(json_build(&a, JSON_BUILD_REAL(M_PIl)) >= 0);
+
+ s = mfree(s);
+ assert_se(json_variant_format(a, 0, &s) >= 0);
+ log_info("GOT: %s\n", s);
+ assert_se(json_parse(s, &b, NULL, NULL) >= 0);
+ assert_se(json_variant_format(b, 0, &t) >= 0);
+ log_info("GOT: %s\n", t);
+
+ assert_se(streq(s, t));
+
+ a = json_variant_unref(a);
+ b = json_variant_unref(b);
+
+ assert_se(json_build(&a, JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR("x", JSON_BUILD_STRING("y")),
+ JSON_BUILD_PAIR("z", JSON_BUILD_STRING("a")),
+ JSON_BUILD_PAIR("b", JSON_BUILD_STRING("c"))
+ )) >= 0);
+
+ assert_se(json_build(&b, JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR("x", JSON_BUILD_STRING("y")),
+ JSON_BUILD_PAIR_CONDITION(false, "p", JSON_BUILD_STRING("q")),
+ JSON_BUILD_PAIR_CONDITION(true, "z", JSON_BUILD_STRING("a")),
+ JSON_BUILD_PAIR_CONDITION(false, "j", JSON_BUILD_ARRAY(JSON_BUILD_STRING("k"), JSON_BUILD_STRING("u"), JSON_BUILD_STRING("i"))),
+ JSON_BUILD_PAIR("b", JSON_BUILD_STRING("c"))
+ )) >= 0);
+
+ assert_se(json_variant_equal(a, b));
+}
+
+static void test_source(void) {
+ static const char data[] =
+ "\n"
+ "\n"
+ "{\n"
+ "\"foo\" : \"bar\", \n"
+ "\"qüüx\" : [ 1, 2, 3,\n"
+ "4,\n"
+ "5 ],\n"
+ "\"miep\" : { \"hallo\" : 1 },\n"
+ "\n"
+ "\"zzzzzz\" \n"
+ ":\n"
+ "[ true, \n"
+ "false, 7.5, {} ]\n"
+ "}\n";
+
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+
+ printf("--- original begin ---\n"
+ "%s"
+ "--- original end ---\n", data);
+
+ assert_se(f = fmemopen((void*) data, strlen(data), "r"));
+
+ assert_se(json_parse_file(f, "waldo", &v, NULL, NULL) >= 0);
+
+ printf("--- non-pretty begin ---\n");
+ json_variant_dump(v, 0, stdout, NULL);
+ printf("\n--- non-pretty end ---\n");
+
+ printf("--- pretty begin ---\n");
+ json_variant_dump(v, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR|JSON_FORMAT_SOURCE, stdout, NULL);
+ printf("--- pretty end ---\n");
+}
+
+static void test_depth(void) {
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+ unsigned i;
+ int r;
+
+ v = JSON_VARIANT_STRING_CONST("start");
+
+ /* Let's verify that the maximum depth checks work */
+
+ for (i = 0;; i++) {
+ _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
+
+ assert_se(i <= UINT16_MAX);
+ if (i & 1)
+ r = json_variant_new_array(&w, &v, 1);
+ else
+ r = json_variant_new_object(&w, (JsonVariant*[]) { JSON_VARIANT_STRING_CONST("key"), v }, 2);
+ if (r == -ELNRNG) {
+ log_info("max depth at %u", i);
+ break;
+ }
+
+ assert_se(r >= 0);
+
+ json_variant_unref(v);
+ v = TAKE_PTR(w);
+ }
+
+ json_variant_dump(v, 0, stdout, NULL);
+ fputs("\n", stdout);
+}
+
+int main(int argc, char *argv[]) {
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_tokenizer("x", -EINVAL);
+ test_tokenizer("", JSON_TOKEN_END);
+ test_tokenizer(" ", JSON_TOKEN_END);
+ test_tokenizer("0", JSON_TOKEN_UNSIGNED, (uintmax_t) 0, JSON_TOKEN_END);
+ test_tokenizer("-0", JSON_TOKEN_INTEGER, (intmax_t) 0, JSON_TOKEN_END);
+ test_tokenizer("1234", JSON_TOKEN_UNSIGNED, (uintmax_t) 1234, JSON_TOKEN_END);
+ test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END);
+ test_tokenizer("18446744073709551615", JSON_TOKEN_UNSIGNED, (uintmax_t) UINT64_MAX, JSON_TOKEN_END);
+ test_tokenizer("-9223372036854775808", JSON_TOKEN_INTEGER, (intmax_t) INT64_MIN, JSON_TOKEN_END);
+ test_tokenizer("18446744073709551616", JSON_TOKEN_REAL, (long double) 18446744073709551616.0L, JSON_TOKEN_END);
+ test_tokenizer("-9223372036854775809", JSON_TOKEN_REAL, (long double) -9223372036854775809.0L, JSON_TOKEN_END);
+ test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END);
+ test_tokenizer("3.141", JSON_TOKEN_REAL, (long double) 3.141, JSON_TOKEN_END);
+ test_tokenizer("0.0", JSON_TOKEN_REAL, (long double) 0.0, JSON_TOKEN_END);
+ test_tokenizer("7e3", JSON_TOKEN_REAL, (long double) 7e3, JSON_TOKEN_END);
+ test_tokenizer("-7e-3", JSON_TOKEN_REAL, (long double) -7e-3, JSON_TOKEN_END);
+ test_tokenizer("true", JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_END);
+ test_tokenizer("false", JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_END);
+ test_tokenizer("null", JSON_TOKEN_NULL, JSON_TOKEN_END);
+ test_tokenizer("{}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("\t {\n} \n", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("[]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("\t [] \n\n", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("\"\"", JSON_TOKEN_STRING, "", JSON_TOKEN_END);
+ test_tokenizer("\"foo\"", JSON_TOKEN_STRING, "foo", JSON_TOKEN_END);
+ test_tokenizer("\"foo\\nfoo\"", JSON_TOKEN_STRING, "foo\nfoo", JSON_TOKEN_END);
+ test_tokenizer("{\"foo\" : \"bar\"}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_STRING, "foo", JSON_TOKEN_COLON, JSON_TOKEN_STRING, "bar", JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("{\"foo\" : [true, false]}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_STRING, "foo", JSON_TOKEN_COLON, JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_COMMA, JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END);
+ test_tokenizer("\"\xef\xbf\xbd\"", JSON_TOKEN_STRING, "\xef\xbf\xbd", JSON_TOKEN_END);
+ test_tokenizer("\"\\ufffd\"", JSON_TOKEN_STRING, "\xef\xbf\xbd", JSON_TOKEN_END);
+ test_tokenizer("\"\\uf\"", -EINVAL);
+ test_tokenizer("\"\\ud800a\"", -EINVAL);
+ test_tokenizer("\"\\udc00\\udc00\"", -EINVAL);
+ test_tokenizer("\"\\ud801\\udc37\"", JSON_TOKEN_STRING, "\xf0\x90\x90\xb7", JSON_TOKEN_END);
+
+ test_tokenizer("[1, 2, -3]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_UNSIGNED, (uintmax_t) 1, JSON_TOKEN_COMMA, JSON_TOKEN_UNSIGNED, (uintmax_t) 2, JSON_TOKEN_COMMA, JSON_TOKEN_INTEGER, (intmax_t) -3, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END);
+
+ test_variant("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1);
+ test_variant("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2);
+ test_variant("{\"foo\" : \"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFF\"}", NULL);
+
+ test_variant("[ 0, -0, 0.0, -0.0, 0.000, -0.000, 0e0, -0e0, 0e+0, -0e-0, 0e-0, -0e000, 0e+000 ]", test_zeroes);
+
+ test_build();
+
+ test_source();
+
+ test_depth();
+
+ return 0;
+}
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index 68399bdb9e..10bf365035 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -1,18 +1,18 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <unistd.h>
-#include "libudev.h"
-
+#include "alloc-util.h"
#include "fd-util.h"
+#include "libudev-list-internal.h"
+#include "libudev-util.h"
#include "log.h"
#include "stdio-util.h"
#include "string-util.h"
-#include "udev-util.h"
-#include "util.h"
static void print_device(struct udev_device *device) {
const char *str;
@@ -331,6 +331,138 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
assert_se(hwdb == NULL);
}
+static void test_util_replace_whitespace_one_len(const char *str, size_t len, const char *expected) {
+ _cleanup_free_ char *result = NULL;
+ int r;
+
+ result = new(char, len + 1);
+ assert_se(result);
+ r = util_replace_whitespace(str, result, len);
+ assert_se((size_t) r == strlen(expected));
+ assert_se(streq(result, expected));
+}
+
+static void test_util_replace_whitespace_one(const char *str, const char *expected) {
+ test_util_replace_whitespace_one_len(str, strlen(str), expected);
+}
+
+static void test_util_replace_whitespace(void) {
+ test_util_replace_whitespace_one("hogehoge", "hogehoge");
+ test_util_replace_whitespace_one("hoge hoge", "hoge_hoge");
+ test_util_replace_whitespace_one(" hoge hoge ", "hoge_hoge");
+ test_util_replace_whitespace_one(" ", "");
+ test_util_replace_whitespace_one("hoge ", "hoge");
+
+ test_util_replace_whitespace_one_len("hoge hoge ", 9, "hoge_hoge");
+ test_util_replace_whitespace_one_len("hoge hoge ", 8, "hoge_hog");
+ test_util_replace_whitespace_one_len("hoge hoge ", 7, "hoge_ho");
+ test_util_replace_whitespace_one_len("hoge hoge ", 6, "hoge_h");
+ test_util_replace_whitespace_one_len("hoge hoge ", 5, "hoge");
+ test_util_replace_whitespace_one_len("hoge hoge ", 4, "hoge");
+ test_util_replace_whitespace_one_len("hoge hoge ", 3, "hog");
+ test_util_replace_whitespace_one_len("hoge hoge ", 2, "ho");
+ test_util_replace_whitespace_one_len("hoge hoge ", 1, "h");
+ test_util_replace_whitespace_one_len("hoge hoge ", 0, "");
+
+ test_util_replace_whitespace_one_len(" hoge hoge ", 9, "hoge_hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 8, "hoge_hog");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 7, "hoge_ho");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 6, "hoge_h");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 5, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 4, "hoge");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 3, "hog");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 2, "ho");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 1, "h");
+ test_util_replace_whitespace_one_len(" hoge hoge ", 0, "");
+}
+
+static void test_util_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) {
+ char result[UTIL_PATH_SIZE];
+ int r;
+
+ r = util_resolve_subsys_kernel(str, result, sizeof(result), read_value);
+ assert_se(r == retval);
+ if (r >= 0)
+ assert_se(streq(result, expected));
+}
+
+static void test_util_resolve_subsys_kernel(void) {
+ test_util_resolve_subsys_kernel_one("hoge", false, -EINVAL, NULL);
+ test_util_resolve_subsys_kernel_one("[hoge", false, -EINVAL, NULL);
+ test_util_resolve_subsys_kernel_one("[hoge/foo", false, -EINVAL, NULL);
+ test_util_resolve_subsys_kernel_one("[hoge/]", false, -ENODEV, NULL);
+
+ test_util_resolve_subsys_kernel_one("[net/lo]", false, 0, "/sys/devices/virtual/net/lo");
+ test_util_resolve_subsys_kernel_one("[net/lo]/", false, 0, "/sys/devices/virtual/net/lo");
+ test_util_resolve_subsys_kernel_one("[net/lo]hoge", false, 0, "/sys/devices/virtual/net/lo/hoge");
+ test_util_resolve_subsys_kernel_one("[net/lo]/hoge", false, 0, "/sys/devices/virtual/net/lo/hoge");
+
+ test_util_resolve_subsys_kernel_one("[net/lo]", true, -EINVAL, NULL);
+ test_util_resolve_subsys_kernel_one("[net/lo]/", true, -EINVAL, NULL);
+ test_util_resolve_subsys_kernel_one("[net/lo]hoge", true, 0, "");
+ test_util_resolve_subsys_kernel_one("[net/lo]/hoge", true, 0, "");
+ test_util_resolve_subsys_kernel_one("[net/lo]address", true, 0, "00:00:00:00:00:00");
+ test_util_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00");
+}
+
+static void test_list(void) {
+ struct udev_list list = {};
+ struct udev_list_entry *e;
+
+ /* empty list */
+ udev_list_init(&list, false);
+ assert_se(!udev_list_get_entry(&list));
+
+ /* unique == false */
+ udev_list_init(&list, false);
+ assert_se(udev_list_entry_add(&list, "aaa", "hoge"));
+ assert_se(udev_list_entry_add(&list, "aaa", "hogehoge"));
+ assert_se(udev_list_entry_add(&list, "bbb", "foo"));
+ e = udev_list_get_entry(&list);
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "hoge"));
+ e = udev_list_entry_get_next(e);
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge"));
+ e = udev_list_entry_get_next(e);
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "foo"));
+ assert_se(!udev_list_entry_get_next(e));
+
+ assert_se(!udev_list_entry_get_by_name(e, "aaa"));
+ assert_se(!udev_list_entry_get_by_name(e, "bbb"));
+ assert_se(!udev_list_entry_get_by_name(e, "ccc"));
+ udev_list_cleanup(&list);
+
+ /* unique == true */
+ udev_list_init(&list, true);
+ assert_se(udev_list_entry_add(&list, "aaa", "hoge"));
+ assert_se(udev_list_entry_add(&list, "aaa", "hogehoge"));
+ assert_se(udev_list_entry_add(&list, "bbb", "foo"));
+ e = udev_list_get_entry(&list);
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge"));
+ e = udev_list_entry_get_next(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "foo"));
+ assert_se(!udev_list_entry_get_next(e));
+
+ e = udev_list_entry_get_by_name(e, "bbb");
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "foo"));
+ e = udev_list_entry_get_by_name(e, "aaa");
+ assert_se(e);
+ assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa"));
+ assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge"));
+ assert_se(!udev_list_entry_get_by_name(e, "ccc"));
+ udev_list_cleanup(&list);
+}
+
int main(int argc, char *argv[]) {
_cleanup_(udev_unrefp) struct udev *udev = NULL;
bool arg_monitor = false;
@@ -399,7 +531,6 @@ int main(int argc, char *argv[]) {
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);
@@ -411,5 +542,10 @@ int main(int argc, char *argv[]) {
if (arg_monitor)
test_monitor(udev);
+ test_util_replace_whitespace();
+ test_util_resolve_subsys_kernel();
+
+ test_list();
+
return EXIT_SUCCESS;
}
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 8ffae8ca03..c6f8c1fb4f 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -65,21 +65,32 @@ static void test_keymaps(void) {
#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
static void dump_special_glyphs(void) {
- assert_cc(ELLIPSIS + 1 == _SPECIAL_GLYPH_MAX);
+ assert_cc(SPECIAL_GLYPH_DEPRESSED_SMILEY + 1 == _SPECIAL_GLYPH_MAX);
log_info("/* %s */", __func__);
log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
- dump_glyph(TREE_VERTICAL);
- dump_glyph(TREE_BRANCH);
- dump_glyph(TREE_RIGHT);
- dump_glyph(TREE_SPACE);
- dump_glyph(TRIANGULAR_BULLET);
- dump_glyph(BLACK_CIRCLE);
- dump_glyph(ARROW);
- dump_glyph(MDASH);
- dump_glyph(ELLIPSIS);
+ dump_glyph(SPECIAL_GLYPH_TREE_VERTICAL);
+ dump_glyph(SPECIAL_GLYPH_TREE_BRANCH);
+ dump_glyph(SPECIAL_GLYPH_TREE_RIGHT);
+ dump_glyph(SPECIAL_GLYPH_TREE_SPACE);
+ dump_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET);
+ dump_glyph(SPECIAL_GLYPH_BLACK_CIRCLE);
+ dump_glyph(SPECIAL_GLYPH_BULLET);
+ dump_glyph(SPECIAL_GLYPH_ARROW);
+ dump_glyph(SPECIAL_GLYPH_MDASH);
+ dump_glyph(SPECIAL_GLYPH_ELLIPSIS);
+ dump_glyph(SPECIAL_GLYPH_MU);
+ dump_glyph(SPECIAL_GLYPH_CHECK_MARK);
+ dump_glyph(SPECIAL_GLYPH_CROSS_MARK);
+ dump_glyph(SPECIAL_GLYPH_ECSTATIC_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_HAPPY_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_NEUTRAL_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_UNHAPPY_SMILEY);
+ dump_glyph(SPECIAL_GLYPH_DEPRESSED_SMILEY);
}
int main(int argc, char *argv[]) {
diff --git a/src/test/test-log.c b/src/test/test-log.c
index c09f40c356..1e010c08fb 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -17,20 +17,27 @@ assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG
assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK)
== LOG_INFO);
+assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(EINVAL)));
+assert_cc(!IS_SYNTHETIC_ERRNO(EINVAL));
+assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(0)));
+assert_cc(!IS_SYNTHETIC_ERRNO(0));
+
#define X10(x) x x x x x x x x x x
#define X100(x) X10(X10(x))
#define X1000(x) X100(X10(x))
-static void test_log_console(void) {
+static void test_log_struct(void) {
log_struct(LOG_INFO,
- "MESSAGE=Waldo PID="PID_FMT, getpid_cached(),
+ "MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),
"SERVICE=piepapo");
-}
-static void test_log_journal(void) {
- log_struct(LOG_INFO,
- "MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
- "SERVICE=foobar");
+ log_struct_errno(LOG_INFO, EILSEQ,
+ "MESSAGE=Waldo PID="PID_FMT": %m (normal)", getpid_cached(),
+ "SERVICE=piepapo");
+
+ log_struct_errno(LOG_INFO, SYNTHETIC_ERRNO(EILSEQ),
+ "MESSAGE=Waldo PID="PID_FMT": %m (synthetic)", getpid_cached(),
+ "SERVICE=piepapo");
log_struct(LOG_INFO,
"MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
@@ -59,10 +66,11 @@ int main(int argc, char* argv[]) {
log_set_target(target);
log_open();
- test_log_console();
- test_log_journal();
+ test_log_struct();
test_long_lines();
}
+ assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN);
+
return 0;
}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index eaea9e4c76..89b760fae4 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -5,13 +5,12 @@
#include "log.h"
#include "loopback-setup.h"
+#include "tests.h"
int main(int argc, char* argv[]) {
int r;
- log_open();
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
r = loopback_setup();
if (r < 0)
diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c
index c10e1681fb..6986405dc6 100644
--- a/src/test/test-mount-util.c
+++ b/src/test/test-mount-util.c
@@ -3,241 +3,9 @@
#include <sys/mount.h>
#include "alloc-util.h"
-#include "def.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "hashmap.h"
-#include "log.h"
-#include "log.h"
#include "mount-util.h"
-#include "path-util.h"
-#include "rm-rf.h"
#include "string-util.h"
-
-static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) {
- long unsigned flags;
-
- assert_se(mount_propagation_flags_from_string(name, &flags) == ret);
-
- if (ret >= 0) {
- const char *c;
-
- assert_se(flags == expected);
-
- c = mount_propagation_flags_to_string(flags);
- if (isempty(name))
- assert_se(isempty(c));
- else
- assert_se(streq(c, name));
- }
-}
-
-static void test_mnt_id(void) {
- _cleanup_fclose_ FILE *f = NULL;
- Hashmap *h;
- Iterator i;
- char *p;
- void *k;
- int r;
-
- assert_se(f = fopen("/proc/self/mountinfo", "re"));
- assert_se(h = hashmap_new(&trivial_hash_ops));
-
- for (;;) {
- _cleanup_free_ char *line = NULL, *path = NULL;
- int mnt_id;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r == 0)
- break;
- assert_se(r > 0);
-
- assert_se(sscanf(line, "%i %*s %*s %*s %ms", &mnt_id, &path) == 2);
-
- assert_se(hashmap_put(h, INT_TO_PTR(mnt_id), path) >= 0);
- path = NULL;
- }
-
- HASHMAP_FOREACH_KEY(p, k, h, i) {
- int mnt_id = PTR_TO_INT(k), mnt_id2;
-
- r = path_get_mnt_id(p, &mnt_id2);
- if (r < 0) {
- log_debug_errno(r, "Failed to get the mnt id of %s: %m\n", p);
- continue;
- }
-
- log_debug("mnt id of %s is %i\n", p, mnt_id2);
-
- if (mnt_id == mnt_id2)
- continue;
-
- /* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really
- * the case */
- assert_se(path_equal_ptr(hashmap_get(h, INT_TO_PTR(mnt_id2)), p));
- }
-
- hashmap_free_free(h);
-}
-
-static void test_path_is_mount_point(void) {
- int fd;
- char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
- _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
- _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL;
- _cleanup_free_ char *dir2 = NULL, *dir2file = NULL;
-
- assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/", NULL, 0) > 0);
- assert_se(path_is_mount_point("//", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("//", NULL, 0) > 0);
-
- assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/proc", NULL, 0) > 0);
- assert_se(path_is_mount_point("/proc/", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/proc/", NULL, 0) > 0);
-
- assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0);
- assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0);
-
- assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/sys", NULL, 0) > 0);
- assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/sys/", NULL, 0) > 0);
-
- /* we'll create a hierarchy of different kinds of dir/file/link
- * layouts:
- *
- * <tmp>/file1, <tmp>/file2
- * <tmp>/link1 -> file1, <tmp>/link2 -> file2
- * <tmp>/dir1/
- * <tmp>/dir1/file
- * <tmp>/dirlink1 -> dir1
- * <tmp>/dirlink1file -> dirlink1/file
- * <tmp>/dir2/
- * <tmp>/dir2/file
- */
-
- /* file mountpoints */
- assert_se(mkdtemp(tmp_dir) != NULL);
- file1 = path_join(NULL, tmp_dir, "file1");
- assert_se(file1);
- file2 = path_join(NULL, tmp_dir, "file2");
- assert_se(file2);
- fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
- fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
- link1 = path_join(NULL, tmp_dir, "link1");
- assert_se(link1);
- assert_se(symlink("file1", link1) == 0);
- link2 = path_join(NULL, tmp_dir, "link2");
- assert_se(link1);
- assert_se(symlink("file2", link2) == 0);
-
- assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(file1, NULL, 0) == 0);
- assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(link1, NULL, 0) == 0);
-
- /* directory mountpoints */
- dir1 = path_join(NULL, tmp_dir, "dir1");
- assert_se(dir1);
- assert_se(mkdir(dir1, 0755) == 0);
- dirlink1 = path_join(NULL, tmp_dir, "dirlink1");
- assert_se(dirlink1);
- assert_se(symlink("dir1", dirlink1) == 0);
- dirlink1file = path_join(NULL, tmp_dir, "dirlink1file");
- assert_se(dirlink1file);
- assert_se(symlink("dirlink1/file", dirlink1file) == 0);
- dir2 = path_join(NULL, tmp_dir, "dir2");
- assert_se(dir2);
- assert_se(mkdir(dir2, 0755) == 0);
-
- assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dir1, NULL, 0) == 0);
- assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0);
-
- /* file in subdirectory mountpoints */
- dir1file = path_join(NULL, dir1, "file");
- assert_se(dir1file);
- fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
-
- assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dir1file, NULL, 0) == 0);
- assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0);
-
- /* these tests will only work as root */
- if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
- int rf, rt, rdf, rdt, rlf, rlt, rl1f, rl1t;
- const char *file2d;
-
- /* files */
- /* capture results in vars, to avoid dangling mounts on failure */
- log_info("%s: %s", __func__, file2);
- rf = path_is_mount_point(file2, NULL, 0);
- rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW);
-
- file2d = strjoina(file2, "/");
- log_info("%s: %s", __func__, file2d);
- rdf = path_is_mount_point(file2d, NULL, 0);
- rdt = path_is_mount_point(file2d, NULL, AT_SYMLINK_FOLLOW);
-
- log_info("%s: %s", __func__, link2);
- rlf = path_is_mount_point(link2, NULL, 0);
- rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW);
-
- assert_se(umount(file2) == 0);
-
- assert_se(rf == 1);
- assert_se(rt == 1);
- assert_se(rdf == -ENOTDIR);
- assert_se(rdt == -ENOTDIR);
- assert_se(rlf == 0);
- assert_se(rlt == 1);
-
- /* dirs */
- dir2file = path_join(NULL, dir2, "file");
- assert_se(dir2file);
- fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
-
- assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0);
-
- log_info("%s: %s", __func__, dir1);
- rf = path_is_mount_point(dir1, NULL, 0);
- rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW);
- log_info("%s: %s", __func__, dirlink1);
- rlf = path_is_mount_point(dirlink1, NULL, 0);
- rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW);
- log_info("%s: %s", __func__, dirlink1file);
- /* its parent is a mount point, but not /file itself */
- rl1f = path_is_mount_point(dirlink1file, NULL, 0);
- rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW);
-
- assert_se(umount(dir1) == 0);
-
- assert_se(rf == 1);
- assert_se(rt == 1);
- assert_se(rlf == 0);
- assert_se(rlt == 1);
- assert_se(rl1f == 0);
- assert_se(rl1t == 0);
-
- } else
- printf("Skipping bind mount file test: %m\n");
-
- assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
-}
+#include "tests.h"
static void test_mount_option_mangle(void) {
char *opts = NULL;
@@ -294,19 +62,8 @@ static void test_mount_option_mangle(void) {
}
int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
- log_set_max_level(LOG_DEBUG);
-
- test_mount_propagation_flags("shared", 0, MS_SHARED);
- test_mount_propagation_flags("slave", 0, MS_SLAVE);
- test_mount_propagation_flags("private", 0, MS_PRIVATE);
- test_mount_propagation_flags(NULL, 0, 0);
- test_mount_propagation_flags("", 0, 0);
- test_mount_propagation_flags("xxxx", -EINVAL, 0);
- test_mount_propagation_flags(" ", -EINVAL, 0);
-
- test_mnt_id();
- test_path_is_mount_point();
test_mount_option_mangle();
return 0;
diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c
new file mode 100644
index 0000000000..6d8bee0d63
--- /dev/null
+++ b/src/test/test-mountpoint-util.c
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/mount.h>
+
+#include "alloc-util.h"
+#include "def.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "hashmap.h"
+#include "log.h"
+#include "log.h"
+#include "mountpoint-util.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "tests.h"
+
+static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) {
+ long unsigned flags;
+
+ log_info("/* %s(%s) */", __func__, name);
+
+ assert_se(mount_propagation_flags_from_string(name, &flags) == ret);
+
+ if (ret >= 0) {
+ const char *c;
+
+ assert_se(flags == expected);
+
+ c = mount_propagation_flags_to_string(flags);
+ if (isempty(name))
+ assert_se(isempty(c));
+ else
+ assert_se(streq(c, name));
+ }
+}
+
+static void test_mnt_id(void) {
+ _cleanup_fclose_ FILE *f = NULL;
+ Hashmap *h;
+ Iterator i;
+ char *p;
+ void *k;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(f = fopen("/proc/self/mountinfo", "re"));
+ assert_se(h = hashmap_new(&trivial_hash_ops));
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL, *path = NULL;
+ int mnt_id;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r == 0)
+ break;
+ assert_se(r > 0);
+
+ assert_se(sscanf(line, "%i %*s %*s %*s %ms", &mnt_id, &path) == 2);
+
+ log_debug("mountinfo: %s → %i", path, mnt_id);
+
+ assert_se(hashmap_put(h, INT_TO_PTR(mnt_id), path) >= 0);
+ path = NULL;
+ }
+
+ HASHMAP_FOREACH_KEY(p, k, h, i) {
+ int mnt_id = PTR_TO_INT(k), mnt_id2;
+
+ r = path_get_mnt_id(p, &mnt_id2);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to get the mnt id of %s: %m\n", p);
+ continue;
+ }
+
+ log_debug("mnt ids of %s are %i, %i\n", p, mnt_id, mnt_id2);
+
+ if (mnt_id == mnt_id2)
+ continue;
+
+ /* The ids don't match? If so, then there are two mounts on the same path, let's check if
+ * that's really the case */
+ char *t = hashmap_get(h, INT_TO_PTR(mnt_id2));
+ log_debug("the other path for mnt id %i is %s\n", mnt_id2, t);
+ assert_se(path_equal(p, t));
+ }
+
+ hashmap_free_free(h);
+}
+
+static void test_path_is_mount_point(void) {
+ int fd;
+ char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
+ _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
+ _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL;
+ _cleanup_free_ char *dir2 = NULL, *dir2file = NULL;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("/", NULL, 0) > 0);
+ assert_se(path_is_mount_point("//", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("//", NULL, 0) > 0);
+
+ assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("/proc", NULL, 0) > 0);
+ assert_se(path_is_mount_point("/proc/", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("/proc/", NULL, 0) > 0);
+
+ assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0);
+ assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0);
+
+ assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("/sys", NULL, 0) > 0);
+ assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0);
+ assert_se(path_is_mount_point("/sys/", NULL, 0) > 0);
+
+ /* we'll create a hierarchy of different kinds of dir/file/link
+ * layouts:
+ *
+ * <tmp>/file1, <tmp>/file2
+ * <tmp>/link1 -> file1, <tmp>/link2 -> file2
+ * <tmp>/dir1/
+ * <tmp>/dir1/file
+ * <tmp>/dirlink1 -> dir1
+ * <tmp>/dirlink1file -> dirlink1/file
+ * <tmp>/dir2/
+ * <tmp>/dir2/file
+ */
+
+ /* file mountpoints */
+ assert_se(mkdtemp(tmp_dir) != NULL);
+ file1 = path_join(tmp_dir, "file1");
+ assert_se(file1);
+ file2 = path_join(tmp_dir, "file2");
+ assert_se(file2);
+ fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+ assert_se(fd > 0);
+ close(fd);
+ fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+ assert_se(fd > 0);
+ close(fd);
+ link1 = path_join(tmp_dir, "link1");
+ assert_se(link1);
+ assert_se(symlink("file1", link1) == 0);
+ link2 = path_join(tmp_dir, "link2");
+ assert_se(link1);
+ assert_se(symlink("file2", link2) == 0);
+
+ assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(file1, NULL, 0) == 0);
+ assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(link1, NULL, 0) == 0);
+
+ /* directory mountpoints */
+ dir1 = path_join(tmp_dir, "dir1");
+ assert_se(dir1);
+ assert_se(mkdir(dir1, 0755) == 0);
+ dirlink1 = path_join(tmp_dir, "dirlink1");
+ assert_se(dirlink1);
+ assert_se(symlink("dir1", dirlink1) == 0);
+ dirlink1file = path_join(tmp_dir, "dirlink1file");
+ assert_se(dirlink1file);
+ assert_se(symlink("dirlink1/file", dirlink1file) == 0);
+ dir2 = path_join(tmp_dir, "dir2");
+ assert_se(dir2);
+ assert_se(mkdir(dir2, 0755) == 0);
+
+ assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(dir1, NULL, 0) == 0);
+ assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0);
+
+ /* file in subdirectory mountpoints */
+ dir1file = path_join(dir1, "file");
+ assert_se(dir1file);
+ fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+ assert_se(fd > 0);
+ close(fd);
+
+ assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(dir1file, NULL, 0) == 0);
+ assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0);
+ assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0);
+
+ /* these tests will only work as root */
+ if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
+ int rf, rt, rdf, rdt, rlf, rlt, rl1f, rl1t;
+ const char *file2d;
+
+ /* files */
+ /* capture results in vars, to avoid dangling mounts on failure */
+ log_info("%s: %s", __func__, file2);
+ rf = path_is_mount_point(file2, NULL, 0);
+ rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW);
+
+ file2d = strjoina(file2, "/");
+ log_info("%s: %s", __func__, file2d);
+ rdf = path_is_mount_point(file2d, NULL, 0);
+ rdt = path_is_mount_point(file2d, NULL, AT_SYMLINK_FOLLOW);
+
+ log_info("%s: %s", __func__, link2);
+ rlf = path_is_mount_point(link2, NULL, 0);
+ rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW);
+
+ assert_se(umount(file2) == 0);
+
+ assert_se(rf == 1);
+ assert_se(rt == 1);
+ assert_se(rdf == -ENOTDIR);
+ assert_se(rdt == -ENOTDIR);
+ assert_se(rlf == 0);
+ assert_se(rlt == 1);
+
+ /* dirs */
+ dir2file = path_join(dir2, "file");
+ assert_se(dir2file);
+ fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
+ assert_se(fd > 0);
+ close(fd);
+
+ assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0);
+
+ log_info("%s: %s", __func__, dir1);
+ rf = path_is_mount_point(dir1, NULL, 0);
+ rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW);
+ log_info("%s: %s", __func__, dirlink1);
+ rlf = path_is_mount_point(dirlink1, NULL, 0);
+ rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW);
+ log_info("%s: %s", __func__, dirlink1file);
+ /* its parent is a mount point, but not /file itself */
+ rl1f = path_is_mount_point(dirlink1file, NULL, 0);
+ rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW);
+
+ assert_se(umount(dir1) == 0);
+
+ assert_se(rf == 1);
+ assert_se(rt == 1);
+ assert_se(rlf == 0);
+ assert_se(rlt == 1);
+ assert_se(rl1f == 0);
+ assert_se(rl1t == 0);
+
+ } else
+ printf("Skipping bind mount file test: %m\n");
+
+ assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_mount_propagation_flags("shared", 0, MS_SHARED);
+ test_mount_propagation_flags("slave", 0, MS_SLAVE);
+ test_mount_propagation_flags("private", 0, MS_PRIVATE);
+ test_mount_propagation_flags(NULL, 0, 0);
+ test_mount_propagation_flags("", 0, 0);
+ test_mount_propagation_flags("xxxx", -EINVAL, 0);
+ test_mount_propagation_flags(" ", -EINVAL, 0);
+
+ test_mnt_id();
+ test_path_is_mount_point();
+
+ return 0;
+}
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index b202739719..cc2efecfd2 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -7,6 +7,7 @@
#include "namespace.h"
#include "process-util.h"
#include "string-util.h"
+#include "tests.h"
#include "util.h"
static void test_tmpdir(const char *id, const char *A, const char *B) {
@@ -46,16 +47,14 @@ static void test_tmpdir(const char *id, const char *A, const char *B) {
assert_se(rmdir(b) >= 0);
}
-static void test_netns(void) {
+static int test_netns(void) {
_cleanup_close_pair_ int s[2] = { -1, -1 };
pid_t pid1, pid2, pid3;
int r, n = 0;
siginfo_t si;
- if (geteuid() > 0) {
- log_info("Skipping test: not root");
- exit(EXIT_TEST_SKIP);
- }
+ if (geteuid() > 0)
+ return log_tests_skipped("not root");
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0);
@@ -102,6 +101,7 @@ static void test_netns(void) {
n += si.si_status;
assert_se(n == 1);
+ return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
@@ -109,8 +109,12 @@ 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();
+ test_setup_logging(LOG_INFO);
+
+ if (!have_namespaces()) {
+ log_tests_skipped("Don't have namespace support");
+ return EXIT_TEST_SKIP;
+ }
assert_se(sd_id128_get_boot(&bid) >= 0);
sd_id128_to_string(bid, boot_id);
@@ -128,7 +132,5 @@ int main(int argc, char *argv[]) {
test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
- test_netns();
-
- return 0;
+ return test_netns();
}
diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c
index eed610b27a..1ebe8d1972 100644
--- a/src/test/test-netlink-manual.c
+++ b/src/test/test-netlink-manual.c
@@ -10,6 +10,7 @@
#include "macro.h"
#include "module-util.h"
+#include "tests.h"
#include "util.h"
static int load_module(const char *mod_name) {
@@ -47,10 +48,14 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
/* skip test if module cannot be loaded */
r = load_module("ipip");
if (r < 0)
- return EXIT_TEST_SKIP;
+ return log_tests_skipped_errno(r, "failed to load module 'ipip'");
+
+ r = load_module("sit");
+ if (r < 0)
+ return log_tests_skipped_errno(r, "failed to load module 'sit'");
if (getuid() != 0)
- return EXIT_TEST_SKIP;
+ return log_tests_skipped("not root");
/* IPIP tunnel */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
@@ -76,10 +81,6 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
assert_se((m = sd_netlink_message_unref(m)) == NULL);
- r = load_module("sit");
- if (r < 0)
- return EXIT_TEST_SKIP;
-
/* sit */
assert_se(sd_rtnl_message_new_link(rtnl, &n, RTM_NEWLINK, 0) >= 0);
assert_se(n);
@@ -113,6 +114,8 @@ int main(int argc, char *argv[]) {
sd_netlink *rtnl;
int r;
+ test_setup_logging(LOG_INFO);
+
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(rtnl);
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index 4ab70f2306..d3dbb54ca1 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -6,6 +6,7 @@
#include "log.h"
#include "namespace.h"
+#include "tests.h"
int main(int argc, char *argv[]) {
const char * const writable[] = {
@@ -43,7 +44,7 @@ int main(int argc, char *argv[]) {
char tmp_dir[] = "/tmp/systemd-private-XXXXXX",
var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX";
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
assert_se(mkdtemp(tmp_dir));
assert_se(mkdtemp(var_tmp_dir));
diff --git a/src/test/test-nscd-flush.c b/src/test/test-nscd-flush.c
new file mode 100644
index 0000000000..97c219596d
--- /dev/null
+++ b/src/test/test-nscd-flush.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "main-func.h"
+#include "nscd-flush.h"
+#include "strv.h"
+#include "tests.h"
+
+static int run(int argc, char *argv[]) {
+ int r;
+
+ test_setup_logging(LOG_DEBUG);
+
+ r = nscd_flush_cache(STRV_MAKE("group", "passwd", "hosts"));
+ if (r < 0)
+ return log_error_errno(r, "Failed to flush NSCD cache");
+
+ return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/src/test/test-nss.c b/src/test/test-nss.c
index 9e543e7557..20aa6cf01f 100644
--- a/src/test/test-nss.c
+++ b/src/test/test-nss.c
@@ -1,22 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dlfcn.h>
-#include <stdlib.h>
#include <net/if.h>
+#include <stdlib.h>
+#include "af-list.h"
+#include "alloc-util.h"
+#include "errno-list.h"
+#include "hexdecoct.h"
+#include "hostname-util.h"
+#include "in-addr-util.h"
+#include "local-addresses.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 "string-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) {
@@ -51,14 +51,12 @@ static const char* af_to_string(int family, char *buf, size_t buf_len) {
}
static void* open_handle(const char* dir, const char* module, int flags) {
- const char *path;
+ const char *path = NULL;
void *handle;
- if (dir) {
+ if (dir)
path = strjoina(dir, "/libnss_", module, ".so.2");
- if (access(path, F_OK) < 0)
- path = strjoina(dir, "/.libs/libnss_", module, ".so.2");
- } else
+ if (!path || access(path, F_OK) < 0)
path = strjoina("libnss_", module, ".so.2");
handle = dlopen(path, flags);
@@ -397,9 +395,7 @@ static int test_one_module(const char* dir,
log_info("======== %s ========", module);
- handle = open_handle(streq(module, "dns") ? NULL : dir,
- module,
- RTLD_LAZY|RTLD_NODELETE);
+ handle = open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE);
if (!handle)
return -EINVAL;
@@ -428,20 +424,19 @@ static int parse_argv(int argc, char **argv,
size_t n_allocated = 0;
if (argc > 1)
- modules = strv_new(argv[1], NULL);
+ modules = strv_new(argv[1]);
else
modules = strv_new(
-#if ENABLE_MYHOSTNAME
+#if ENABLE_NSS_MYHOSTNAME
"myhostname",
#endif
-#if ENABLE_RESOLVE
+#if ENABLE_NSS_RESOLVE
"resolve",
#endif
-#if ENABLE_MACHINED
+#if ENABLE_NSS_MYMACHINES
"mymachines",
#endif
- "dns",
- NULL);
+ "dns");
if (!modules)
return -ENOMEM;
@@ -472,7 +467,7 @@ static int parse_argv(int argc, char **argv,
if (!hostname)
return -ENOMEM;
- names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname, NULL);
+ names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname);
if (!names)
return -ENOMEM;
diff --git a/src/test/test-os-util.c b/src/test/test-os-util.c
index 8d8b52d7f6..c215a2e99e 100644
--- a/src/test/test-os-util.c
+++ b/src/test/test-os-util.c
@@ -4,6 +4,7 @@
#include "log.h"
#include "os-util.h"
+#include "tests.h"
static void test_path_is_os_tree(void) {
assert_se(path_is_os_tree("/") > 0);
@@ -12,9 +13,7 @@ static void test_path_is_os_tree(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_path_is_os_tree();
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
index e9aef5e882..d732f402f0 100644
--- a/src/test/test-parse-util.c
+++ b/src/test/test-parse-util.c
@@ -726,10 +726,12 @@ static void test_parse_dev(void) {
assert_se(parse_dev("5", &dev) == -EINVAL);
assert_se(parse_dev("5:", &dev) == -EINVAL);
assert_se(parse_dev(":5", &dev) == -EINVAL);
+ assert_se(parse_dev("-1:-1", &dev) == -EINVAL);
#if SIZEOF_DEV_T < 8
assert_se(parse_dev("4294967295:4294967295", &dev) == -EINVAL);
#endif
assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11);
+ assert_se(parse_dev("0:0", &dev) >= 0 && major(dev) == 0 && minor(dev) == 0);
}
static void test_parse_errno(void) {
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
index 892293cb10..f208559358 100644
--- a/src/test/test-path-lookup.c
+++ b/src/test/test-path-lookup.c
@@ -8,6 +8,7 @@
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
static void test_paths(UnitFileScope scope) {
char template[] = "/tmp/test-path-lookup.XXXXXXX";
@@ -40,6 +41,8 @@ static void test_user_and_global_paths(void) {
unsigned k = 0;
assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0);
+ assert_se(unsetenv("XDG_DATA_DIRS") == 0);
+ assert_se(unsetenv("XDG_CONFIG_DIRS") == 0);
assert_se(lookup_paths_init(&lp_global, UNIT_FILE_GLOBAL, 0, NULL) == 0);
assert_se(lookup_paths_init(&lp_user, UNIT_FILE_USER, 0, NULL) == 0);
@@ -76,9 +79,7 @@ static void print_generator_binary_paths(UnitFileScope scope) {
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_paths(UNIT_FILE_SYSTEM);
test_paths(UNIT_FILE_USER);
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 35b27bcedd..8854a94f6c 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -6,12 +6,13 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "macro.h"
-#include "mount-util.h"
+#include "mountpoint-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
#include "util.h"
#define test_path_compare(a, b, result) { \
@@ -80,10 +81,10 @@ static void test_path(void) {
test_path_simplify("///.//", "/.", "/");
test_path_simplify("///.//.///", "/./.", "/");
test_path_simplify("////.././///../.", "/.././../.", "/../..");
- test_path_simplify(".", ".", "");
- test_path_simplify("./", ".", "");
- test_path_simplify(".///.//./.", "./././.", "");
- test_path_simplify(".///.//././/", "./././.", "");
+ test_path_simplify(".", ".", ".");
+ test_path_simplify("./", ".", ".");
+ test_path_simplify(".///.//./.", "./././.", ".");
+ test_path_simplify(".///.//././/", "./././.", ".");
test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
"/./aaa/././.bbb/../c./d.dd/..eeee/.",
"/aaa/.bbb/../c./d.dd/..eeee");
@@ -231,23 +232,47 @@ static void test_prefixes(void) {
static void test_path_join(void) {
-#define test_join(root, path, rest, expected) { \
+#define test_join(expected, ...) { \
_cleanup_free_ char *z = NULL; \
- z = path_join(root, path, rest); \
+ z = path_join(__VA_ARGS__); \
+ log_debug("got \"%s\", expected \"%s\"", z, expected); \
assert_se(streq(z, expected)); \
}
- test_join("/root", "/a/b", "/c", "/root/a/b/c");
- test_join("/root", "a/b", "c", "/root/a/b/c");
- test_join("/root", "/a/b", "c", "/root/a/b/c");
- test_join("/root", "/", "c", "/root/c");
- test_join("/root", "/", NULL, "/root/");
-
- test_join(NULL, "/a/b", "/c", "/a/b/c");
- test_join(NULL, "a/b", "c", "a/b/c");
- test_join(NULL, "/a/b", "c", "/a/b/c");
- test_join(NULL, "/", "c", "/c");
- test_join(NULL, "/", NULL, "/");
+ test_join("/root/a/b/c", "/root", "/a/b", "/c");
+ test_join("/root/a/b/c", "/root", "a/b", "c");
+ test_join("/root/a/b/c", "/root", "/a/b", "c");
+ test_join("/root/c", "/root", "/", "c");
+ test_join("/root/", "/root", "/", NULL);
+
+ test_join("/a/b/c", "", "/a/b", "/c");
+ test_join("a/b/c", "", "a/b", "c");
+ test_join("/a/b/c", "", "/a/b", "c");
+ test_join("/c", "", "/", "c");
+ test_join("/", "", "/", NULL);
+
+ test_join("/a/b/c", NULL, "/a/b", "/c");
+ test_join("a/b/c", NULL, "a/b", "c");
+ test_join("/a/b/c", NULL, "/a/b", "c");
+ test_join("/c", NULL, "/", "c");
+ test_join("/", NULL, "/", NULL);
+
+ test_join("", "", NULL);
+ test_join("", NULL, "");
+ test_join("", NULL, NULL);
+
+ test_join("foo/bar", "foo", "bar");
+ test_join("foo/bar", "", "foo", "bar");
+ test_join("foo/bar", NULL, "foo", NULL, "bar");
+ test_join("foo/bar", "", "foo", "", "bar", "");
+ test_join("foo/bar", "", "", "", "", "foo", "", "", "", "bar", "", "", "");
+
+ test_join("//foo///bar//", "", "/", "", "/foo/", "", "/", "", "/bar/", "", "/", "");
+ test_join("/foo/bar/", "/", "foo", "/", "bar", "/");
+ test_join("foo/bar/baz", "foo", "bar", "baz");
+ test_join("foo/bar/baz", "foo/", "bar", "/baz");
+ test_join("foo//bar//baz", "foo/", "/bar/", "/baz");
+ test_join("//foo////bar////baz//", "//foo/", "///bar/", "///baz//");
}
static void test_fsck_exists(void) {
@@ -292,7 +317,7 @@ static void test_strv_resolve(void) {
assert_se(mkdtemp(tmp_dir) != NULL);
- search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
+ search_dirs = strv_new("/dir1", "/dir2", "/dir3");
assert_se(search_dirs);
STRV_FOREACH(d, search_dirs) {
char *p = strappend(tmp_dir, *d);
@@ -405,6 +430,7 @@ static void test_file_in_same_dir(void) {
}
static void test_last_path_component(void) {
+ assert_se(last_path_component(NULL) == NULL);
assert_se(streq(last_path_component("a/b/c"), "c"));
assert_se(streq(last_path_component("a/b/c/"), "c/"));
assert_se(streq(last_path_component("/"), "/"));
@@ -423,6 +449,45 @@ static void test_last_path_component(void) {
assert_se(streq(last_path_component("/a/"), "a/"));
}
+static void test_path_extract_filename_one(const char *input, const char *output, int ret) {
+ _cleanup_free_ char *k = NULL;
+ int r;
+
+ r = path_extract_filename(input, &k);
+ log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror(-r), strnull(output), strerror(-ret));
+ assert_se(streq_ptr(k, output));
+ assert_se(r == ret);
+}
+
+static void test_path_extract_filename(void) {
+ test_path_extract_filename_one(NULL, NULL, -EINVAL);
+ test_path_extract_filename_one("a/b/c", "c", 0);
+ test_path_extract_filename_one("a/b/c/", "c", 0);
+ test_path_extract_filename_one("/", NULL, -EINVAL);
+ test_path_extract_filename_one("//", NULL, -EINVAL);
+ test_path_extract_filename_one("///", NULL, -EINVAL);
+ test_path_extract_filename_one(".", NULL, -EINVAL);
+ test_path_extract_filename_one("./.", NULL, -EINVAL);
+ test_path_extract_filename_one("././", NULL, -EINVAL);
+ test_path_extract_filename_one("././/", NULL, -EINVAL);
+ test_path_extract_filename_one("/foo/a", "a", 0);
+ test_path_extract_filename_one("/foo/a/", "a", 0);
+ test_path_extract_filename_one("", NULL, -EINVAL);
+ test_path_extract_filename_one("a", "a", 0);
+ test_path_extract_filename_one("a/", "a", 0);
+ test_path_extract_filename_one("/a", "a", 0);
+ test_path_extract_filename_one("/a/", "a", 0);
+ test_path_extract_filename_one("/////////////a/////////////", "a", 0);
+ test_path_extract_filename_one("xx/.", NULL, -EINVAL);
+ test_path_extract_filename_one("xx/..", NULL, -EINVAL);
+ test_path_extract_filename_one("..", NULL, -EINVAL);
+ test_path_extract_filename_one("/..", NULL, -EINVAL);
+ test_path_extract_filename_one("../", NULL, -EINVAL);
+ test_path_extract_filename_one(".", NULL, -EINVAL);
+ test_path_extract_filename_one("/.", NULL, -EINVAL);
+ test_path_extract_filename_one("./", NULL, -EINVAL);
+}
+
static void test_filename_is_valid(void) {
char foo[FILENAME_MAX+2];
int i;
@@ -505,10 +570,29 @@ static void test_empty_or_root(void) {
assert_se(!empty_or_root("//yy//"));
}
+static void test_path_startswith_set(void) {
+
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/bar", "/zzz"), ""));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/", "/zzz"), "bar"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo", "/zzz"), "bar"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/", "/zzz"), "foo/bar"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "", "/zzz"), NULL));
+
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/bar", "/zzz"), NULL));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/", "/zzz"), "bar2"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo", "/zzz"), "bar2"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/", "/zzz"), "foo/bar2"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "", "/zzz"), NULL));
+
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/bar", "/zzz"), NULL));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/", "/zzz"), NULL));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo", "/zzz"), NULL));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/", "/zzz"), "foo2/bar"));
+ assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL));
+}
+
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_path();
test_path_equal_root();
@@ -522,10 +606,12 @@ int main(int argc, char **argv) {
test_prefix_root();
test_file_in_same_dir();
test_last_path_component();
+ test_path_extract_filename();
test_filename_is_valid();
test_hidden_or_backup_file();
test_skip_dev_prefix();
test_empty_or_root();
+ test_path_startswith_set();
test_systemd_installation_has_version(argv[1]); /* NULL is OK */
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 209eb2e366..07a0e413ee 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -12,6 +12,7 @@
#include "macro.h"
#include "manager.h"
#include "mkdir.h"
+#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
@@ -32,16 +33,12 @@ static int setup_test(Manager **m) {
assert_se(m);
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice_errno(r, "Skipping test: cgroupfs not available");
- return -EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp);
- if (MANAGER_SKIP_TEST(r)) {
- log_notice_errno(r, "Skipping test: manager_new: %m");
- return -EXIT_TEST_SKIP;
- }
+ if (MANAGER_SKIP_TEST(r))
+ return log_tests_skipped_errno(r, "manager_new");
assert_se(r >= 0);
assert_se(manager_startup(tmp, NULL, NULL) >= 0);
@@ -106,7 +103,7 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
}
}
- assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
+ assert_se(unit_stop(unit) >= 0);
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
}
@@ -117,7 +114,7 @@ static void test_path_exists(Manager *m) {
assert_se(m);
assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -130,7 +127,7 @@ static void test_path_existsglob(Manager *m) {
assert_se(m);
assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -147,7 +144,7 @@ static void test_path_changed(Manager *m) {
assert_se(touch(test_path) >= 0);
assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
f = fopen(test_path, "w");
assert_se(f);
@@ -166,7 +163,7 @@ static void test_path_modified(Manager *m) {
assert_se(touch(test_path) >= 0);
assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
f = fopen(test_path, "w");
assert_se(f);
@@ -182,7 +179,7 @@ static void test_path_unit(Manager *m) {
assert_se(m);
assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -198,7 +195,7 @@ static void test_path_directorynotempty(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
/* MakeDirectory default to no */
assert_se(access(test_path, F_OK) < 0);
@@ -219,7 +216,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
/* Check if the directory has been created */
assert_se(access(test_path, F_OK) >= 0);
@@ -230,7 +227,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
assert_se((s.st_mode & S_IRWXG) == 0040);
assert_se((s.st_mode & S_IRWXO) == 0004);
- assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
+ assert_se(unit_stop(unit) >= 0);
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
}
@@ -247,15 +244,16 @@ int main(int argc, char *argv[]) {
};
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ _cleanup_free_ char *test_path = NULL;
const test_function_t *test = NULL;
Manager *m = NULL;
umask(022);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
- assert_se(set_unit_path(get_testdata_dir("/test-path")) >= 0);
+ test_path = path_join(get_testdata_dir(), "test-path");
+ assert_se(set_unit_path(test_path) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
for (test = tests; test && *test; test++) {
@@ -263,8 +261,8 @@ int main(int argc, char *argv[]) {
/* We create a clean environment for each test */
r = setup_test(&m);
- if (r < 0)
- return -r;
+ if (r != 0)
+ return r;
(*test)(m);
diff --git a/src/test/test-pretty-print.c b/src/test/test-pretty-print.c
new file mode 100644
index 0000000000..53ec512ec3
--- /dev/null
+++ b/src/test/test-pretty-print.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio.h>
+
+#include "alloc-util.h"
+#include "macro.h"
+#include "pretty-print.h"
+#include "strv.h"
+#include "tests.h"
+
+static void test_terminal_urlify(void) {
+ _cleanup_free_ char *formatted = NULL;
+
+ assert_se(terminal_urlify("https://www.freedesktop.org/wiki/Software/systemd/", "systemd homepage", &formatted) >= 0);
+ printf("Hey, considere visiting the %s right now! It is very good!\n", formatted);
+
+ formatted = mfree(formatted);
+
+ assert_se(terminal_urlify_path("/etc/fstab", "this link to your /etc/fstab", &formatted) >= 0);
+ printf("Or click on %s to have a look at it!\n", formatted);
+}
+
+static void test_cat_files(void) {
+ assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT);
+ assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0);
+
+ if (access("/etc/fstab", R_OK) >= 0)
+ assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ test_terminal_urlify();
+ test_cat_files();
+
+ print_separator();
+
+ return 0;
+}
diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c
index 89c41d8ce7..bc5fdd15b2 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -10,40 +10,30 @@
#define SET_SIZE 1024*4
-static int unsigned_compare(const void *a, const void *b) {
- const unsigned *x = a, *y = b;
-
- if (*x < *y)
- return -1;
-
- if (*x > *y)
- return 1;
-
- return 0;
+static int unsigned_compare(const unsigned *a, const unsigned *b) {
+ return CMP(*a, *b);
}
static void test_unsigned(void) {
- unsigned buffer[SET_SIZE], i;
- Prioq *q;
+ _cleanup_(prioq_freep) Prioq *q = NULL;
+ unsigned buffer[SET_SIZE], i, u, n;
srand(0);
- q = prioq_new(trivial_compare_func);
- assert_se(q);
+ assert_se(q = prioq_new(trivial_compare_func));
for (i = 0; i < ELEMENTSOF(buffer); i++) {
- unsigned u;
-
u = (unsigned) rand();
buffer[i] = u;
assert_se(prioq_put(q, UINT_TO_PTR(u), NULL) >= 0);
+
+ n = prioq_size(q);
+ assert_se(prioq_remove(q, UINT_TO_PTR(u), &n) == 0);
}
- qsort(buffer, ELEMENTSOF(buffer), sizeof(buffer[0]), unsigned_compare);
+ typesafe_qsort(buffer, ELEMENTSOF(buffer), unsigned_compare);
for (i = 0; i < ELEMENTSOF(buffer); i++) {
- unsigned u;
-
assert_se(prioq_size(q) == ELEMENTSOF(buffer) - i);
u = PTR_TO_UINT(prioq_pop(q));
@@ -51,7 +41,6 @@ static void test_unsigned(void) {
}
assert_se(prioq_isempty(q));
- prioq_free(q);
}
struct test {
@@ -59,90 +48,59 @@ struct test {
unsigned idx;
};
-static int test_compare(const void *a, const void *b) {
- const struct test *x = a, *y = b;
-
- if (x->value < y->value)
- return -1;
-
- if (x->value > y->value)
- return 1;
-
- return 0;
+static int test_compare(const struct test *x, const struct test *y) {
+ return CMP(x->value, y->value);
}
-static void test_hash(const void *a, struct siphash *state) {
- const struct test *x = a;
-
+static void test_hash(const struct test *x, struct siphash *state) {
siphash24_compress(&x->value, sizeof(x->value), state);
}
-static const struct hash_ops test_hash_ops = {
- .hash = test_hash,
- .compare = test_compare
-};
+DEFINE_PRIVATE_HASH_OPS(test_hash_ops, struct test, test_hash, test_compare);
static void test_struct(void) {
- Prioq *q;
- Set *s;
+ _cleanup_(prioq_freep) Prioq *q = NULL;
+ _cleanup_(set_freep) Set *s = NULL;
unsigned previous = 0, i;
- int r;
+ struct test *t;
srand(0);
- q = prioq_new(test_compare);
- assert_se(q);
-
- s = set_new(&test_hash_ops);
- assert_se(s);
+ assert_se(q = prioq_new((compare_func_t) test_compare));
+ assert_se(s = set_new(&test_hash_ops));
for (i = 0; i < SET_SIZE; i++) {
- struct test *t;
-
- t = new0(struct test, 1);
- assert_se(t);
+ assert_se(t = new0(struct test, 1));
t->value = (unsigned) rand();
- r = prioq_put(q, t, &t->idx);
- assert_se(r >= 0);
+ assert_se(prioq_put(q, t, &t->idx) >= 0);
- if (i % 4 == 0) {
- r = set_consume(s, t);
- assert_se(r >= 0);
- }
+ if (i % 4 == 0)
+ assert_se(set_consume(s, t) >= 0);
}
- for (;;) {
- struct test *t;
-
- t = set_steal_first(s);
- if (!t)
- break;
-
- r = prioq_remove(q, t, &t->idx);
- assert_se(r > 0);
+ while ((t = set_steal_first(s))) {
+ assert_se(prioq_remove(q, t, &t->idx) == 1);
+ assert_se(prioq_remove(q, t, &t->idx) == 0);
+ assert_se(prioq_remove(q, t, NULL) == 0);
free(t);
}
for (i = 0; i < SET_SIZE * 3 / 4; i++) {
- struct test *t;
-
assert_se(prioq_size(q) == (SET_SIZE * 3 / 4) - i);
- t = prioq_pop(q);
- assert_se(t);
-
+ assert_se(t = prioq_pop(q));
+ assert_se(prioq_remove(q, t, &t->idx) == 0);
+ assert_se(prioq_remove(q, t, NULL) == 0);
assert_se(previous <= t->value);
+
previous = t->value;
free(t);
}
assert_se(prioq_isempty(q));
- prioq_free(q);
-
assert_se(set_isempty(s));
- set_free(s);
}
int main(int argc, char* argv[]) {
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
index 8f77e084b6..b0fc217d51 100644
--- a/src/test/test-proc-cmdline.c
+++ b/src/test/test-proc-cmdline.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
+#include "env-util.h"
#include "log.h"
#include "macro.h"
#include "proc-cmdline.h"
@@ -19,29 +20,79 @@ static int parse_item(const char *key, const char *value, void *data) {
}
static void test_proc_cmdline_parse(void) {
- assert_se(proc_cmdline_parse(parse_item, &obj, true) >= 0);
+ log_info("/* %s */", __func__);
+
+ assert_se(proc_cmdline_parse(parse_item, &obj, PROC_CMDLINE_STRIP_RD_PREFIX) >= 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));
+static void test_proc_cmdline_override(void) {
+ log_info("/* %s */", __func__);
- 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));
+ assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"") == 0);
+
+ /* Test if the override works */
+ _cleanup_free_ char *line = NULL, *value = NULL;
+ assert_se(proc_cmdline(&line) >= 0);
+
+ /* Test if parsing makes uses of the override */
+ assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\""));
+ assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux"));
+ value = mfree(value);
+
+ assert_se(proc_cmdline_get_key("some_arg_with_space", 0, &value) > 0 && streq_ptr(value, "foo bar"));
+ value = mfree(value);
+
+ assert_se(proc_cmdline_get_key("and_one_more", 0, &value) > 0 && streq_ptr(value, "zzz aaa"));
+ value = mfree(value);
+}
+
+static int parse_item_given(const char *key, const char *value, void *data) {
+ assert_se(key);
+ assert_se(data);
+
+ bool *strip = data;
+
+ log_info("%s: option <%s> = <%s>", __func__, key, strna(value));
+ if (proc_cmdline_key_streq(key, "foo_bar"))
+ assert_se(streq(value, "quux"));
+ else if (proc_cmdline_key_streq(key, "wuff-piep"))
+ assert_se(streq(value, "tuet "));
+ else if (proc_cmdline_key_streq(key, "space"))
+ assert_se(streq(value, "x y z"));
+ else if (proc_cmdline_key_streq(key, "miepf"))
+ assert_se(streq(value, "uuu"));
+ else if (in_initrd() && *strip && proc_cmdline_key_streq(key, "zumm"))
+ assert_se(!value);
+ else if (in_initrd() && !*strip && proc_cmdline_key_streq(key, "rd.zumm"))
+ assert_se(!value);
+ else
+ assert_not_reached("Bad key!");
+
+ return 0;
+}
+
+static void test_proc_cmdline_given(bool flip_initrd) {
+ log_info("/* %s (flip: %s) */", __func__, yes_no(flip_initrd));
+
+ if (flip_initrd)
+ in_initrd_force(!in_initrd());
+
+ bool t = true, f = false;
+ assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm space='x y z' miepf=\"uuu\"",
+ parse_item_given, &t, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0);
+
+ assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm space='x y z' miepf=\"uuu\"",
+ parse_item_given, &f, 0) >= 0);
+
+ if (flip_initrd)
+ in_initrd_force(!in_initrd());
}
static void test_proc_cmdline_get_key(void) {
_cleanup_free_ char *value = NULL;
- putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm");
+ log_info("/* %s */", __func__);
+ assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm spaaace='ö ü ß' ticks=\"''\"") == 0);
assert_se(proc_cmdline_get_key("", 0, &value) == -EINVAL);
assert_se(proc_cmdline_get_key("abc", 0, NULL) == 0);
@@ -73,12 +124,18 @@ static void test_proc_cmdline_get_key(void) {
assert_se(proc_cmdline_get_key("zumm", 0, &value) == 0 && value == NULL);
assert_se(proc_cmdline_get_key("zumm", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && value == NULL);
assert_se(proc_cmdline_get_key("zumm", 0, NULL) > 0);
+
+ assert_se(proc_cmdline_get_key("spaaace", 0, &value) > 0 && streq_ptr(value, "ö ü ß"));
+ value = mfree(value);
+
+ assert_se(proc_cmdline_get_key("ticks", 0, &value) > 0 && streq_ptr(value, "''"));
}
static void test_proc_cmdline_get_bool(void) {
bool value = false;
- putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep");
+ log_info("/* %s */", __func__);
+ assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep") == 0);
assert_se(proc_cmdline_get_bool("", &value) == -EINVAL);
assert_se(proc_cmdline_get_bool("abc", &value) == 0 && value == false);
@@ -93,7 +150,30 @@ static void test_proc_cmdline_get_bool(void) {
assert_se(proc_cmdline_get_bool("quux", &value) == -EINVAL && value == false);
}
+static void test_proc_cmdline_get_key_many(void) {
+ _cleanup_free_ char *value1 = NULL, *value2 = NULL, *value3 = NULL, *value4 = NULL, *value5 = NULL, *value6 = NULL;
+
+ log_info("/* %s */", __func__);
+ assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm SPACE='one two' doubleticks=\" aaa aaa \"") == 0);
+
+ assert_se(proc_cmdline_get_key_many(0,
+ "wuff-piep", &value3,
+ "foo_bar", &value1,
+ "idontexist", &value2,
+ "zumm", &value4,
+ "SPACE", &value5,
+ "doubleticks", &value6) == 4);
+
+ assert_se(streq_ptr(value1, "quux"));
+ assert_se(!value2);
+ assert_se(streq_ptr(value3, "tuet"));
+ assert_se(!value4);
+ assert_se(streq_ptr(value5, "one two"));
+ assert_se(streq_ptr(value6, " aaa aaa "));
+}
+
static void test_proc_cmdline_key_streq(void) {
+ log_info("/* %s */", __func__);
assert_se(proc_cmdline_key_streq("", ""));
assert_se(proc_cmdline_key_streq("a", "a"));
@@ -110,6 +190,7 @@ static void test_proc_cmdline_key_streq(void) {
}
static void test_proc_cmdline_key_startswith(void) {
+ log_info("/* %s */", __func__);
assert_se(proc_cmdline_key_startswith("", ""));
assert_se(proc_cmdline_key_startswith("x", ""));
@@ -124,15 +205,38 @@ static void test_proc_cmdline_key_startswith(void) {
assert_se(!proc_cmdline_key_startswith("foo-bar", "foo_xx"));
}
+static void test_runlevel_to_target(void) {
+ log_info("/* %s */", __func__);
+
+ 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_proc_cmdline_parse();
+ test_proc_cmdline_override();
+ test_proc_cmdline_given(false);
+ /* Repeat the same thing, but now flip our ininitrdness */
+ test_proc_cmdline_given(true);
test_proc_cmdline_key_streq();
test_proc_cmdline_key_startswith();
test_proc_cmdline_get_key();
test_proc_cmdline_get_bool();
+ test_proc_cmdline_get_key_many();
test_runlevel_to_target();
return 0;
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index fd4d17408d..5c87db08f5 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -17,6 +17,7 @@
#include "fd-util.h"
#include "log.h"
#include "macro.h"
+#include "missing.h"
#include "parse-util.h"
#include "process-util.h"
#include "signal-util.h"
@@ -24,6 +25,7 @@
#include "string-util.h"
#include "terminal-util.h"
#include "test-helper.h"
+#include "tests.h"
#include "util.h"
#include "virt.h"
@@ -180,15 +182,24 @@ static void test_get_process_cmdline_harder(void) {
_cleanup_free_ char *line = NULL;
pid_t pid;
- if (geteuid() != 0)
+ if (geteuid() != 0) {
+ log_info("Skipping %s: not root", __func__);
return;
+ }
+
+ if (!have_namespaces()) {
+ log_notice("Testing without namespaces, skipping %s", __func__);
+ return;
+ }
#if 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)
+ if (RUNNING_ON_VALGRIND) {
+ log_info("Skipping %s: running on valgrind", __func__);
return;
+ }
#endif
pid = fork();
@@ -206,15 +217,21 @@ static void test_get_process_cmdline_harder(void) {
assert_se(pid == 0);
assert_se(unshare(CLONE_NEWNS) >= 0);
- assert_se(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) >= 0);
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
+ log_warning_errno(errno, "mount(..., \"/\", MS_SLAVE|MS_REC, ...) failed: %m");
+ assert_se(IN_SET(errno, EPERM, EACCES));
+ return;
+ }
fd = mkostemp(path, O_CLOEXEC);
assert_se(fd >= 0);
+ /* Note that we don't unmount the following bind-mount at the end of the test because the kernel
+ * will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
- assert(errno == EACCES);
+ assert_se(IN_SET(errno, EPERM, EACCES));
return;
}
@@ -394,12 +411,17 @@ static void test_rename_process_now(const char *p, int ret) {
log_info("comm = <%s>", comm);
assert_se(strneq(comm, p, TASK_COMM_LEN-1));
- assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
+ r = get_process_cmdline(0, 0, false, &cmdline);
+ assert_se(r >= 0);
/* we cannot expect cmdline to be renamed properly without privileges */
if (geteuid() == 0) {
- log_info("cmdline = <%s>", cmdline);
- assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
- assert_se(startswith(p, cmdline));
+ if (r == 0 && detect_container() > 0)
+ log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
+ else {
+ log_info("cmdline = <%s>", cmdline);
+ assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
+ assert_se(startswith(p, cmdline));
+ }
} else
log_info("cmdline = <%s> (not verified)", cmdline);
}
@@ -581,9 +603,7 @@ static void test_ioprio_class_from_to_string(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
saved_argc = argc;
saved_argv = argv;
diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c
index a4760b54a3..94c431f7e6 100644
--- a/src/test/test-random-util.c
+++ b/src/test/test-random-util.c
@@ -3,15 +3,16 @@
#include "hexdecoct.h"
#include "random-util.h"
#include "log.h"
+#include "tests.h"
-static void test_acquire_random_bytes(bool high_quality_required) {
+static void test_genuine_random_bytes(RandomFlags flags) {
uint8_t buf[16] = {};
unsigned i;
log_info("/* %s */", __func__);
for (i = 1; i < sizeof buf; i++) {
- assert_se(acquire_random_bytes(buf, i, high_quality_required) == 0);
+ assert_se(genuine_random_bytes(buf, i, flags) == 0);
if (i + 1 < sizeof buf)
assert_se(buf[i] == 0);
@@ -19,14 +20,14 @@ static void test_acquire_random_bytes(bool high_quality_required) {
}
}
-static void test_pseudorandom_bytes(void) {
+static void test_pseudo_random_bytes(void) {
uint8_t buf[16] = {};
unsigned i;
log_info("/* %s */", __func__);
for (i = 1; i < sizeof buf; i++) {
- pseudorandom_bytes(buf, i);
+ pseudo_random_bytes(buf, i);
if (i + 1 < sizeof buf)
assert_se(buf[i] == 0);
@@ -34,15 +35,33 @@ static void test_pseudorandom_bytes(void) {
}
}
+static void test_rdrand(void) {
+ int r, i;
+
+ for (i = 0; i < 10; i++) {
+ unsigned long x = 0;
+
+ r = rdrand(&x);
+ if (r < 0) {
+ log_error_errno(r, "RDRAND failed: %m");
+ return;
+ }
+
+ printf("%lx\n", x);
+ }
+}
+
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
+
+ test_genuine_random_bytes(RANDOM_EXTEND_WITH_PSEUDO);
+ test_genuine_random_bytes(0);
+ test_genuine_random_bytes(RANDOM_BLOCK);
+ test_genuine_random_bytes(RANDOM_ALLOW_RDRAND);
- test_acquire_random_bytes(false);
- test_acquire_random_bytes(true);
+ test_pseudo_random_bytes();
- test_pseudorandom_bytes();
+ test_rdrand();
return 0;
}
diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c
index 15701b2712..771719a267 100644
--- a/src/test/test-rlimit-util.c
+++ b/src/test/test-rlimit-util.c
@@ -5,6 +5,7 @@
#include "alloc-util.h"
#include "capability-util.h"
#include "macro.h"
+#include "missing.h"
#include "rlimit-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index c986284155..1aa178182b 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -19,20 +19,18 @@ int main(int argc, char *argv[]) {
Service *ser;
int r;
+ test_setup_logging(LOG_INFO);
+
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice_errno(r, "Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
/* prepare the test */
- assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(set_unit_path(get_testdata_dir()) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
- if (MANAGER_SKIP_TEST(r)) {
- log_notice_errno(r, "Skipping test: manager_new: %m");
- return EXIT_TEST_SKIP;
- }
+ if (MANAGER_SKIP_TEST(r))
+ return log_tests_skipped_errno(r, "manager_new");
assert_se(r >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
diff --git a/src/test/test-sd-hwdb.c b/src/test/test-sd-hwdb.c
new file mode 100644
index 0000000000..17ca6a0e27
--- /dev/null
+++ b/src/test/test-sd-hwdb.c
@@ -0,0 +1,74 @@
+#include "sd-hwdb.h"
+
+#include "alloc-util.h"
+#include "errno.h"
+#include "tests.h"
+
+static int test_failed_enumerate(void) {
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
+ const char *key, *value;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ r = sd_hwdb_new(&hwdb);
+ if (r == -ENOENT)
+ return r;
+ assert_se(r == 0);
+
+ assert_se(sd_hwdb_seek(hwdb, "no-such-modalias-should-exist") == 0);
+
+ assert_se(sd_hwdb_enumerate(hwdb, &key, &value) == 0);
+ assert_se(sd_hwdb_enumerate(hwdb, &key, NULL) == -EINVAL);
+ assert_se(sd_hwdb_enumerate(hwdb, NULL, &value) == -EINVAL);
+
+ return 0;
+}
+
+#define DELL_MODALIAS \
+ "evdev:atkbd:dmi:bvnXXX:bvrYYY:bdZZZ:svnDellXXX:pnYYY"
+
+static void test_basic_enumerate(void) {
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
+ const char *key, *value;
+ size_t len1 = 0, len2 = 0;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(sd_hwdb_new(&hwdb) == 0);
+
+ assert_se(sd_hwdb_seek(hwdb, DELL_MODALIAS) == 0);
+
+ for (;;) {
+ r = sd_hwdb_enumerate(hwdb, &key, &value);
+ assert(IN_SET(r, 0, 1));
+ if (r == 0)
+ break;
+ assert(key);
+ assert(value);
+ log_debug("A: \"%s\" → \"%s\"", key, value);
+ len1 += strlen(key) + strlen(value);
+ }
+
+ SD_HWDB_FOREACH_PROPERTY(hwdb, DELL_MODALIAS, key, value) {
+ log_debug("B: \"%s\" → \"%s\"", key, value);
+ len2 += strlen(key) + strlen(value);
+ }
+
+ assert_se(len1 == len2);
+}
+
+int main(int argc, char *argv[]) {
+ int r;
+
+ test_setup_logging(LOG_DEBUG);
+
+ r = test_failed_enumerate();
+ if (r < 0)
+ return log_tests_skipped_errno(r, "cannot open hwdb");
+
+ test_basic_enumerate();
+
+ return 0;
+}
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index d82cb5c1c5..fbfeedd536 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -20,6 +20,7 @@
#include "seccomp-util.h"
#include "set.h"
#include "string-util.h"
+#include "tests.h"
#include "util.h"
#include "virt.h"
@@ -35,6 +36,8 @@ static void test_seccomp_arch_to_string(void) {
uint32_t a, b;
const char *name;
+ log_info("/* %s */", __func__);
+
a = seccomp_arch_native();
assert_se(a > 0);
name = seccomp_arch_to_string(a);
@@ -46,6 +49,8 @@ static void test_seccomp_arch_to_string(void) {
static void test_architecture_table(void) {
const char *n, *n2;
+ log_info("/* %s */", __func__);
+
NULSTR_FOREACH(n,
"native\0"
"x86\0"
@@ -74,6 +79,8 @@ static void test_architecture_table(void) {
}
static void test_syscall_filter_set_find(void) {
+ log_info("/* %s */", __func__);
+
assert_se(!syscall_filter_set_find(NULL));
assert_se(!syscall_filter_set_find(""));
assert_se(!syscall_filter_set_find("quux"));
@@ -88,10 +95,16 @@ static void test_filter_sets(void) {
unsigned i;
int r;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
pid_t pid;
@@ -104,11 +117,11 @@ static void test_filter_sets(void) {
if (pid == 0) { /* Child? */
int fd;
- /* if we look at the default set (or one that includes it), whitelist instead of blacklist */
+ /* If we look at the default set (or one that includes it), whitelist instead of blacklist */
if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE))
- r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW);
+ r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true);
else
- r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN));
+ r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true);
if (r < 0)
_exit(EXIT_FAILURE);
@@ -128,11 +141,50 @@ static void test_filter_sets(void) {
}
}
+static void test_filter_sets_ordered(void) {
+ size_t i;
+
+ log_info("/* %s */", __func__);
+
+ /* Ensure "@default" always remains at the beginning of the list */
+ assert_se(SYSCALL_FILTER_SET_DEFAULT == 0);
+ assert_se(streq(syscall_filter_sets[0].name, "@default"));
+
+ for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
+ const char *k, *p = NULL;
+
+ /* Make sure each group has a description */
+ assert_se(!isempty(syscall_filter_sets[0].help));
+
+ /* Make sure the groups are ordered alphabetically, except for the first entry */
+ assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
+
+ NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
+
+ /* Ensure each syscall list is in itself ordered, but groups before names */
+ assert_se(!p ||
+ (*p == '@' && *k != '@') ||
+ (((*p == '@' && *k == '@') ||
+ (*p != '@' && *k != '@')) &&
+ strcmp(p, k) < 0));
+
+ p = k;
+ }
+ }
+}
+
static void test_restrict_namespace(void) {
char *s = NULL;
unsigned long ul;
pid_t pid;
+ if (!have_namespaces()) {
+ log_notice("Testing without namespaces, skipping %s", __func__);
+ return;
+ }
+
+ log_info("/* %s */", __func__);
+
assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, ""));
s = mfree(s);
assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt"));
@@ -160,10 +212,14 @@ static void test_restrict_namespace(void) {
assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
s = mfree(s);
- if (!is_seccomp_available())
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping remaining tests in %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping remaining tests in %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -223,13 +279,22 @@ static void test_restrict_namespace(void) {
static void test_protect_sysctl(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
- if (detect_container() > 0) /* in containers _sysctl() is likely missing anyway */
+ /* in containers _sysctl() is likely missing anyway */
+ if (detect_container() > 0) {
+ log_notice("Testing in container, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -256,10 +321,16 @@ static void test_protect_sysctl(void) {
static void test_restrict_address_families(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -339,13 +410,22 @@ static void test_restrict_address_families(void) {
static void test_restrict_realtime(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
- if (detect_container() > 0) /* in containers RT privs are likely missing anyway */
+ /* in containers RT privs are likely missing anyway */
+ if (detect_container() > 0) {
+ log_notice("Testing in container, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -377,10 +457,16 @@ static void test_restrict_realtime(void) {
static void test_memory_deny_write_execute_mmap(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -421,10 +507,16 @@ static void test_memory_deny_write_execute_shmat(void) {
int shmid;
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
shmid = shmget(IPC_PRIVATE, page_size(), 0);
assert_se(shmid >= 0);
@@ -467,10 +559,16 @@ static void test_memory_deny_write_execute_shmat(void) {
static void test_restrict_archs(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -501,10 +599,16 @@ static void test_restrict_archs(void) {
static void test_load_syscall_filter_set_raw(void) {
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
pid = fork();
assert_se(pid >= 0);
@@ -515,7 +619,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0);
- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL, true) >= 0);
assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0);
@@ -526,7 +630,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0);
#endif
- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0);
assert_se(access("/", F_OK) < 0);
assert_se(errno == EUCLEAN);
@@ -542,7 +646,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0);
#endif
- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0);
assert_se(access("/", F_OK) < 0);
assert_se(errno == EILSEQ);
@@ -558,7 +662,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0);
#endif
- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0);
assert_se(access("/", F_OK) < 0);
assert_se(errno == EILSEQ);
@@ -575,7 +679,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0);
#endif
- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0);
assert_se(access("/", F_OK) < 0);
assert_se(errno == EILSEQ);
@@ -593,10 +697,16 @@ static void test_lock_personality(void) {
unsigned long current;
pid_t pid;
- if (!is_seccomp_available())
+ log_info("/* %s */", __func__);
+
+ if (!is_seccomp_available()) {
+ log_notice("Seccomp not available, skipping %s", __func__);
return;
- if (geteuid() != 0)
+ }
+ if (geteuid() != 0) {
+ log_notice("Not root, skipping %s", __func__);
return;
+ }
assert_se(opinionated_personality(&current) >= 0);
@@ -636,44 +746,14 @@ static void test_lock_personality(void) {
assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
-static void test_filter_sets_ordered(void) {
- size_t i;
-
- /* Ensure "@default" always remains at the beginning of the list */
- assert_se(SYSCALL_FILTER_SET_DEFAULT == 0);
- assert_se(streq(syscall_filter_sets[0].name, "@default"));
-
- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
- const char *k, *p = NULL;
-
- /* Make sure each group has a description */
- assert_se(!isempty(syscall_filter_sets[0].help));
-
- /* Make sure the groups are ordered alphabetically, except for the first entry */
- assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
-
- NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
-
- /* Ensure each syscall list is in itself ordered, but groups before names */
- assert_se(!p ||
- (*p == '@' && *k != '@') ||
- (((*p == '@' && *k == '@') ||
- (*p != '@' && *k != '@')) &&
- strcmp(p, k) < 0));
-
- p = k;
- }
- }
-}
-
int main(int argc, char *argv[]) {
-
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
test_seccomp_arch_to_string();
test_architecture_table();
test_syscall_filter_set_find();
test_filter_sets();
+ test_filter_sets_ordered();
test_restrict_namespace();
test_protect_sysctl();
test_restrict_address_families();
@@ -683,7 +763,6 @@ int main(int argc, char *argv[]) {
test_restrict_archs();
test_load_syscall_filter_set_raw();
test_lock_personality();
- test_filter_sets_ordered();
return 0;
}
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
index 6caeb843f3..59b4f71946 100644
--- a/src/test/test-selinux.c
+++ b/src/test/test-selinux.c
@@ -7,6 +7,7 @@
#include "log.h"
#include "selinux-util.h"
#include "string-util.h"
+#include "tests.h"
#include "time-util.h"
#include "util.h"
@@ -92,8 +93,7 @@ int main(int argc, char **argv) {
if (argc >= 2)
path = argv[1];
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
test_testing();
test_loading();
diff --git a/src/test/test-serialize.c b/src/test/test-serialize.c
new file mode 100644
index 0000000000..a57d5db2b1
--- /dev/null
+++ b/src/test/test-serialize.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "log.h"
+#include "serialize.h"
+#include "strv.h"
+#include "tests.h"
+#include "tmpfile-util.h"
+
+char long_string[LONG_LINE_MAX+1];
+
+static void test_serialize_item(void) {
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
+ log_info("/* %s (%s) */", __func__, fn);
+
+ assert_se(serialize_item(f, "a", NULL) == 0);
+ assert_se(serialize_item(f, "a", "bbb") == 1);
+ assert_se(serialize_item(f, "a", "bbb") == 1);
+ assert_se(serialize_item(f, "a", long_string) == -EINVAL);
+ assert_se(serialize_item(f, long_string, "a") == -EINVAL);
+ assert_se(serialize_item(f, long_string, long_string) == -EINVAL);
+
+ rewind(f);
+
+ _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL;
+ assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
+ assert_se(streq(line1, "a=bbb"));
+ assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
+ assert_se(streq(line2, "a=bbb"));
+ assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0);
+ assert_se(streq(line3, ""));
+}
+
+static void test_serialize_item_escaped(void) {
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
+ log_info("/* %s (%s) */", __func__, fn);
+
+ assert_se(serialize_item_escaped(f, "a", NULL) == 0);
+ assert_se(serialize_item_escaped(f, "a", "bbb") == 1);
+ assert_se(serialize_item_escaped(f, "a", "bbb") == 1);
+ assert_se(serialize_item_escaped(f, "a", long_string) == -EINVAL);
+ assert_se(serialize_item_escaped(f, long_string, "a") == -EINVAL);
+ assert_se(serialize_item_escaped(f, long_string, long_string) == -EINVAL);
+
+ rewind(f);
+
+ _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL;
+ assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
+ assert_se(streq(line1, "a=bbb"));
+ assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
+ assert_se(streq(line2, "a=bbb"));
+ assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0);
+ assert_se(streq(line3, ""));
+}
+
+static void test_serialize_usec(void) {
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
+ log_info("/* %s (%s) */", __func__, fn);
+
+ assert_se(serialize_usec(f, "usec1", USEC_INFINITY) == 0);
+ assert_se(serialize_usec(f, "usec2", 0) == 1);
+ assert_se(serialize_usec(f, "usec3", USEC_INFINITY-1) == 1);
+
+ rewind(f);
+
+ _cleanup_free_ char *line1 = NULL, *line2 = NULL;
+ usec_t x;
+
+ assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0);
+ assert_se(streq(line1, "usec2=0"));
+ assert_se(deserialize_usec(line1 + 6, &x) == 0);
+ assert_se(x == 0);
+
+ assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0);
+ assert_se(startswith(line2, "usec3="));
+ assert_se(deserialize_usec(line2 + 6, &x) == 0);
+ assert_se(x == USEC_INFINITY-1);
+}
+
+static void test_serialize_strv(void) {
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+
+ char **strv = STRV_MAKE("a", "b", "foo foo",
+ "nasty1 \"",
+ "\"nasty2 ",
+ "nasty3 '",
+ "\"nasty4 \"",
+ "nasty5\n",
+ "\nnasty5\nfoo=bar",
+ "\nnasty5\nfoo=bar");
+
+ assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
+ log_info("/* %s (%s) */", __func__, fn);
+
+ assert_se(serialize_strv(f, "strv1", NULL) == 0);
+ assert_se(serialize_strv(f, "strv2", STRV_MAKE_EMPTY) == 0);
+ assert_se(serialize_strv(f, "strv3", strv) == 1);
+ assert_se(serialize_strv(f, "strv4", STRV_MAKE(long_string)) == -EINVAL);
+
+ rewind(f);
+
+ _cleanup_strv_free_ char **strv2 = NULL;
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ int r;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r == 0)
+ break;
+ assert_se(r > 0);
+
+ const char *t = startswith(line, "strv3=");
+ assert_se(t);
+
+ char *un;
+ assert_se(cunescape(t, 0, &un) >= 0);
+ assert_se(strv_consume(&strv2, un) >= 0);
+ }
+
+ assert_se(strv_equal(strv, strv2));
+}
+
+static void test_deserialize_environment(void) {
+ _cleanup_strv_free_ char **env;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(env = strv_new("A=1"));
+
+ assert_se(deserialize_environment("B=2", &env) >= 0);
+ assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0);
+
+ assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e")));
+
+ assert_se(deserialize_environment("foo\\", &env) < 0);
+ assert_se(deserialize_environment("bar\\_baz", &env) < 0);
+}
+
+static void test_serialize_environment(void) {
+ _cleanup_strv_free_ char **env = NULL, **env2 = NULL;
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ assert_se(fmkostemp_safe(fn, "r+", &f) == 0);
+ log_info("/* %s (%s) */", __func__, fn);
+
+ assert_se(env = strv_new("A=1",
+ "B=2",
+ "C=ąęółń",
+ "D=D=a\\x0Ab",
+ "FOO%%=a\177b\nc\td e"));
+
+ assert_se(serialize_strv(f, "env", env) == 1);
+ assert_se(fflush_and_check(f) == 0);
+
+ rewind(f);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ const char *l;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ assert_se(r >= 0);
+
+ if (r == 0)
+ break;
+
+ l = strstrip(line);
+
+ assert_se(startswith(l, "env="));
+
+ r = deserialize_environment(l+4, &env2);
+ assert_se(r >= 0);
+ }
+ assert_se(feof(f));
+
+ assert_se(strv_equal(env, env2));
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ memset(long_string, 'x', sizeof(long_string)-1);
+ char_array_0(long_string);
+
+ test_serialize_item();
+ test_serialize_item_escaped();
+ test_serialize_usec();
+ test_serialize_strv();
+ test_deserialize_environment();
+ test_serialize_environment();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-set-disable-mempool.c b/src/test/test-set-disable-mempool.c
new file mode 100644
index 0000000000..aea83d2679
--- /dev/null
+++ b/src/test/test-set-disable-mempool.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <pthread.h>
+
+#include "process-util.h"
+#include "set.h"
+#include "tests.h"
+
+#define NUM 100
+
+static void* thread(void *p) {
+ Set **s = p;
+
+ assert_se(s);
+ assert_se(*s);
+
+ assert_se(!is_main_thread());
+ assert_se(set_size(*s) == NUM);
+ *s = set_free(*s);
+
+ return NULL;
+}
+
+static void test_one(const char *val) {
+ pthread_t t;
+ int x[NUM] = {};
+ unsigned i;
+ Set *s;
+
+ log_info("Testing with SYSTEMD_MEMPOOL=%s", val);
+ assert_se(setenv("SYSTEMD_MEMPOOL", val, true) == 0);
+ assert_se(is_main_thread());
+
+ assert_se(s = set_new(NULL));
+ for (i = 0; i < NUM; i++)
+ assert_se(set_put(s, &x[i]));
+
+ assert_se(pthread_create(&t, NULL, thread, &s) == 0);
+ assert_se(pthread_join(t, NULL) == 0);
+
+ assert_se(!s);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_one("0");
+ /* The value $SYSTEMD_MEMPOOL= is cached. So the following
+ * test should also succeed. */
+ test_one("1");
+
+ return 0;
+}
diff --git a/src/test/test-set.c b/src/test/test-set.c
index 6307403e4c..340edeb65f 100644
--- a/src/test/test-set.c
+++ b/src/test/test-set.c
@@ -45,6 +45,24 @@ static void test_set_free_with_destructor(void) {
assert_se(items[3].seen == 0);
}
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, void, trivial_hash_func, trivial_compare_func, Item, item_seen);
+
+static void test_set_free_with_hash_ops(void) {
+ Set *m;
+ struct Item items[4] = {};
+ unsigned i;
+
+ assert_se(m = set_new(&item_hash_ops));
+ for (i = 0; i < ELEMENTSOF(items) - 1; i++)
+ assert_se(set_put(m, items + i) == 1);
+
+ m = set_free(m);
+ assert_se(items[0].seen == 1);
+ assert_se(items[1].seen == 1);
+ assert_se(items[2].seen == 1);
+ assert_se(items[3].seen == 0);
+}
+
static void test_set_put(void) {
_cleanup_set_free_ Set *m = NULL;
@@ -64,6 +82,7 @@ static void test_set_put(void) {
int main(int argc, const char *argv[]) {
test_set_steal_first();
test_set_free_with_destructor();
+ test_set_free_with_hash_ops();
test_set_put();
return 0;
diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c
index c9343364d4..d2666dd1d8 100644
--- a/src/test/test-sigbus.c
+++ b/src/test/test-sigbus.c
@@ -2,12 +2,14 @@
#include <sys/mman.h>
+#if HAVE_VALGRIND_VALGRIND_H
+# include <valgrind/valgrind.h>
+#endif
+
#include "fd-util.h"
#include "sigbus.h"
+#include "tests.h"
#include "util.h"
-#if HAVE_VALGRIND_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
int main(int argc, char *argv[]) {
_cleanup_close_ int fd = -1;
@@ -15,14 +17,16 @@ int main(int argc, char *argv[]) {
void *addr = NULL;
uint8_t *p;
+ test_setup_logging(LOG_INFO);
+
+#if HAS_FEATURE_ADDRESS_SANITIZER
+ return log_tests_skipped("address-sanitizer is enabled");
+#endif
#if HAVE_VALGRIND_VALGRIND_H
if (RUNNING_ON_VALGRIND)
- return EXIT_TEST_SKIP;
+ return log_tests_skipped("This test cannot run on valgrind");
#endif
-#ifdef __SANITIZE_ADDRESS__
- return EXIT_TEST_SKIP;
-#endif
sigbus_install();
assert_se(sigbus_pop(&addr) == 0);
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index 5286442e26..2a6d5e765a 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <inttypes.h>
#include <linux/fiemap.h>
#include <stdio.h>
@@ -7,13 +8,16 @@
#include "log.h"
#include "sleep-config.h"
#include "strv.h"
+#include "tests.h"
#include "util.h"
static void test_parse_sleep_config(void) {
const char *verb;
+ log_info("/* %s */", __func__);
+
FOREACH_STRING(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")
- assert_se(parse_sleep_config(verb, NULL, NULL, NULL) == 0);
+ assert_se(parse_sleep_config(verb, NULL, NULL, NULL, NULL) == 0);
}
static int test_fiemap(const char *path) {
@@ -21,42 +25,44 @@ static int test_fiemap(const char *path) {
_cleanup_close_ int fd = -1;
int r;
+ log_info("/* %s */", __func__);
+
fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
if (fd < 0)
return log_error_errno(errno, "failed to open %s: %m", path);
r = read_fiemap(fd, &fiemap);
- if (r == -EOPNOTSUPP) {
- log_info("Skipping test, not supported");
- exit(EXIT_TEST_SKIP);
- }
+ if (r == -EOPNOTSUPP)
+ exit(log_tests_skipped("Not supported"));
if (r < 0)
return log_error_errno(r, "Unable to read extent map for '%s': %m", path);
log_info("extent map information for %s:", path);
- log_info("\t start: %llu", fiemap->fm_start);
- log_info("\t length: %llu", fiemap->fm_length);
- log_info("\t flags: %u", fiemap->fm_flags);
- log_info("\t number of mapped extents: %u", fiemap->fm_mapped_extents);
- log_info("\t extent count: %u", fiemap->fm_extent_count);
+ log_info("\t start: %" PRIu64, (uint64_t) fiemap->fm_start);
+ log_info("\t length: %" PRIu64, (uint64_t) fiemap->fm_length);
+ log_info("\t flags: %" PRIu32, fiemap->fm_flags);
+ log_info("\t number of mapped extents: %" PRIu32, fiemap->fm_mapped_extents);
+ log_info("\t extent count: %" PRIu32, fiemap->fm_extent_count);
if (fiemap->fm_extent_count > 0)
- log_info("\t first extent location: %llu",
- fiemap->fm_extents[0].fe_physical / page_size());
+ log_info("\t first extent location: %" PRIu64,
+ (uint64_t) (fiemap->fm_extents[0].fe_physical / page_size()));
return 0;
}
static void test_sleep(void) {
_cleanup_strv_free_ char
- **standby = strv_new("standby", NULL),
- **mem = strv_new("mem", NULL),
- **disk = strv_new("disk", NULL),
- **suspend = strv_new("suspend", NULL),
- **reboot = strv_new("reboot", NULL),
- **platform = strv_new("platform", NULL),
- **shutdown = strv_new("shutdown", NULL),
- **freez = strv_new("freeze", NULL);
+ **standby = strv_new("standby"),
+ **mem = strv_new("mem"),
+ **disk = strv_new("disk"),
+ **suspend = strv_new("suspend"),
+ **reboot = strv_new("reboot"),
+ **platform = strv_new("platform"),
+ **shutdown = strv_new("shutdown"),
+ **freez = strv_new("freeze");
int r;
- log_info("/* configuration */");
+ log_info("/* %s */", __func__);
+
+ log_info("/= configuration =/");
log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0));
log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0));
log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0));
@@ -66,7 +72,7 @@ static void test_sleep(void) {
log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0));
log_info("Freeze configured: %s", yes_no(can_sleep_state(freez) > 0));
- log_info("/* running system */");
+ log_info("/= running system =/");
r = can_sleep("suspend");
log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
r = can_sleep("hibernate");
@@ -80,8 +86,7 @@ static void test_sleep(void) {
int main(int argc, char* argv[]) {
int i, r = 0, k;
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
if (getuid() != 0)
log_warning("This program is unlikely to work for unprivileged users");
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index ac2ea52a5c..07ff487834 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -6,16 +6,24 @@
#include "alloc-util.h"
#include "async.h"
+#include "escape.h"
+#include "exit-status.h"
#include "fd-util.h"
#include "in-addr-util.h"
+#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "missing_network.h"
#include "process-util.h"
#include "socket-util.h"
#include "string-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_ifname_valid(void) {
+ log_info("/* %s */", __func__);
+
assert(ifname_valid("foo"));
assert(ifname_valid("eth0"));
@@ -38,61 +46,121 @@ static void test_ifname_valid(void) {
assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
}
-static void test_socket_address_parse(void) {
+static void test_socket_address_parse_one(const char *in, int ret, int family, const char *expected) {
SocketAddress a;
+ _cleanup_free_ char *out = NULL;
+ int r;
+
+ r = socket_address_parse(&a, in);
+ if (r >= 0)
+ assert_se(socket_address_print(&a, &out) >= 0);
+
+ log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in,
+ r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-");
+ assert_se(r == ret);
+ if (r >= 0) {
+ assert_se(a.sockaddr.sa.sa_family == family);
+ assert_se(streq(out, expected ?: in));
+ }
+}
+
+#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
+assert_cc(sizeof(((struct sockaddr_un){}).sun_path) == 108);
- assert_se(socket_address_parse(&a, "junk") < 0);
- assert_se(socket_address_parse(&a, "192.168.1.1") < 0);
- assert_se(socket_address_parse(&a, ".168.1.1") < 0);
- assert_se(socket_address_parse(&a, "989.168.1.1") < 0);
- assert_se(socket_address_parse(&a, "192.168.1.1:65536") < 0);
- assert_se(socket_address_parse(&a, "192.168.1.1:0") < 0);
- assert_se(socket_address_parse(&a, "0") < 0);
- assert_se(socket_address_parse(&a, "65536") < 0);
+static void test_socket_address_parse(void) {
+ log_info("/* %s */", __func__);
+
+ test_socket_address_parse_one("junk", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("192.168.1.1", -EINVAL, 0, NULL);
+ test_socket_address_parse_one(".168.1.1", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("989.168.1.1", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("192.168.1.1:65536", -ERANGE, 0, NULL);
+ test_socket_address_parse_one("192.168.1.1:0", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("0", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("65536", -ERANGE, 0, NULL);
- assert_se(socket_address_parse(&a, "65535") >= 0);
+ const int default_family = socket_ipv6_is_supported() ? AF_INET6 : AF_INET;
+
+ test_socket_address_parse_one("65535", 0, default_family, "[::]:65535");
/* 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, "[::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);
+ test_socket_address_parse_one("[::1]", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("[::1]8888", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("::1", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("[::1]:0", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("[::1]:65536", -ERANGE, 0, NULL);
+ test_socket_address_parse_one("[a:b:1]:8888", -EINVAL, 0, NULL);
- assert_se(socket_address_parse(&a, "8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == (socket_ipv6_is_supported() ? AF_INET6 : AF_INET));
+ test_socket_address_parse_one("8888", 0, default_family, "[::]:8888");
+ test_socket_address_parse_one("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888", 0, AF_INET6,
+ "[2001:db8:0:85a3::ac1f:8001]:8888");
+ test_socket_address_parse_one("[::1]:8888", 0, AF_INET6, NULL);
+ test_socket_address_parse_one("192.168.1.254:8888", 0, AF_INET, NULL);
+ test_socket_address_parse_one("/foo/bar", 0, AF_UNIX, NULL);
+ test_socket_address_parse_one("/", 0, AF_UNIX, NULL);
+ test_socket_address_parse_one("@abstract", 0, AF_UNIX, NULL);
- 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);
+ {
+ char aaa[SUN_PATH_LEN + 1] = "@";
- assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET6);
+ memset(aaa + 1, 'a', SUN_PATH_LEN - 1);
+ char_array_0(aaa);
- assert_se(socket_address_parse(&a, "192.168.1.254:8888") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_INET);
+ test_socket_address_parse_one(aaa, -EINVAL, 0, NULL);
- assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_UNIX);
+ aaa[SUN_PATH_LEN - 1] = '\0';
+ test_socket_address_parse_one(aaa, 0, AF_UNIX, NULL);
+ }
- assert_se(socket_address_parse(&a, "@abstract") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_UNIX);
+ test_socket_address_parse_one("vsock:2:1234", 0, AF_VSOCK, NULL);
+ test_socket_address_parse_one("vsock::1234", 0, AF_VSOCK, NULL);
+ test_socket_address_parse_one("vsock:2:1234x", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("vsock:2x:1234", -EINVAL, 0, NULL);
+ test_socket_address_parse_one("vsock:2", -EINVAL, 0, NULL);
+}
- assert_se(socket_address_parse(&a, "vsock::1234") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_VSOCK);
- assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
- assert_se(a.sockaddr.sa.sa_family == AF_VSOCK);
- assert_se(socket_address_parse(&a, "vsock:2:1234x") < 0);
- assert_se(socket_address_parse(&a, "vsock:2x:1234") < 0);
- assert_se(socket_address_parse(&a, "vsock:2") < 0);
+static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) {
+ _cleanup_free_ char *out = NULL, *c = NULL;
+
+ SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } },
+ .size = offsetof(struct sockaddr_un, sun_path) + len_in,
+ .type = SOCK_STREAM,
+ };
+ memcpy(a.sockaddr.un.sun_path, in, len_in);
+
+ assert_se(socket_address_print(&a, &out) >= 0);
+ assert_se(c = cescape(in));
+ log_info("\"%s\" → \"%s\" (expect \"%s\")", in, out, expected);
+ assert_se(streq(out, expected));
+}
+
+static void test_socket_print_unix(void) {
+ log_info("/* %s */", __func__);
+
+ /* Some additional tests for abstract addresses which we don't parse */
+
+ test_socket_print_unix_one("\0\0\0\0", 4, "@\\000\\000\\000");
+ test_socket_print_unix_one("@abs", 5, "@abs");
+ test_socket_print_unix_one("\n", 2, "\\n");
+ test_socket_print_unix_one("", 1, "<unnamed>");
+ test_socket_print_unix_one("\0", 1, "<unnamed>");
+ test_socket_print_unix_one("\0_________________________there's 108 characters in this string_____________________________________________", 108,
+ "@_________________________there\\'s 108 characters in this string_____________________________________________");
+ test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108,
+ "////////////////////////////////////////////////////////////////////////////////////////////////////////////");
+ test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 109,
+ "////////////////////////////////////////////////////////////////////////////////////////////////////////////");
+ test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
}
static void test_socket_address_parse_netlink(void) {
SocketAddress a;
+ log_info("/* %s */", __func__);
+
assert_se(socket_address_parse_netlink(&a, "junk") < 0);
assert_se(socket_address_parse_netlink(&a, "") < 0);
@@ -116,8 +184,9 @@ static void test_socket_address_parse_netlink(void) {
}
static void test_socket_address_equal(void) {
- SocketAddress a;
- SocketAddress b;
+ SocketAddress a, b;
+
+ log_info("/* %s */", __func__);
assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
assert_se(socket_address_parse(&b, "192.168.1.1:888") >= 0);
@@ -167,6 +236,8 @@ static void test_socket_address_equal(void) {
static void test_socket_address_get_path(void) {
SocketAddress a;
+ log_info("/* %s */", __func__);
+
assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
assert_se(!socket_address_get_path(&a));
@@ -186,6 +257,8 @@ static void test_socket_address_get_path(void) {
static void test_socket_address_is(void) {
SocketAddress a;
+ log_info("/* %s */", __func__);
+
assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
assert_se(socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM));
assert_se(!socket_address_is(&a, "route", SOCK_STREAM));
@@ -195,6 +268,8 @@ static void test_socket_address_is(void) {
static void test_socket_address_is_netlink(void) {
SocketAddress a;
+ log_info("/* %s */", __func__);
+
assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
assert_se(socket_address_is_netlink(&a, "route 10"));
assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888"));
@@ -202,9 +277,10 @@ static void test_socket_address_is_netlink(void) {
}
static void test_in_addr_is_null(void) {
-
union in_addr_union i = {};
+ log_info("/* %s */", __func__);
+
assert_se(in_addr_is_null(AF_INET, &i) == true);
assert_se(in_addr_is_null(AF_INET6, &i) == true);
@@ -225,6 +301,7 @@ static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigne
}
static void test_in_addr_prefix_intersect(void) {
+ log_info("/* %s */", __func__);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
@@ -266,6 +343,7 @@ static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigne
}
static void test_in_addr_prefix_next(void) {
+ log_info("/* %s */", __func__);
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
@@ -285,7 +363,6 @@ static void test_in_addr_prefix_next(void) {
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
-
}
static void test_in_addr_to_string_one(int f, const char *addr) {
@@ -299,6 +376,8 @@ static void test_in_addr_to_string_one(int f, const char *addr) {
}
static void test_in_addr_to_string(void) {
+ log_info("/* %s */", __func__);
+
test_in_addr_to_string_one(AF_INET, "192.168.0.1");
test_in_addr_to_string_one(AF_INET, "10.11.12.13");
test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
@@ -323,6 +402,8 @@ static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex
}
static void test_in_addr_ifindex_to_string(void) {
+ log_info("/* %s */", __func__);
+
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");
@@ -338,6 +419,7 @@ static void test_in_addr_ifindex_from_string_auto(void) {
int family, ifindex;
union in_addr_union ua;
+ log_info("/* %s */", __func__);
/* 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);
@@ -381,6 +463,9 @@ static void test_sockaddr_equal(void) {
.vm.svm_port = 0,
.vm.svm_cid = VMADDR_CID_ANY,
};
+
+ log_info("/* %s */", __func__);
+
assert_se(sockaddr_equal(&a, &a));
assert_se(sockaddr_equal(&a, &b));
assert_se(sockaddr_equal(&d, &d));
@@ -391,6 +476,8 @@ static void test_sockaddr_equal(void) {
}
static void test_sockaddr_un_len(void) {
+ log_info("/* %s */", __func__);
+
static const struct sockaddr_un fs = {
.sun_family = AF_UNIX,
.sun_path = "/foo/bar/waldo",
@@ -401,7 +488,7 @@ static void test_sockaddr_un_len(void) {
.sun_path = "\0foobar",
};
- assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path));
+ assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1);
assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1));
}
@@ -409,6 +496,8 @@ static void test_in_addr_is_multicast(void) {
union in_addr_union a, b;
int f;
+ log_info("/* %s */", __func__);
+
assert_se(in_addr_from_string_auto("192.168.3.11", &f, &a) >= 0);
assert_se(in_addr_is_multicast(f, &a) == 0);
@@ -425,13 +514,14 @@ static void test_in_addr_is_multicast(void) {
static void test_getpeercred_getpeergroups(void) {
int r;
+ log_info("/* %s */", __func__);
+
r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
static const gid_t gids[] = { 3, 4, 5, 6, 7 };
gid_t *test_gids;
- _cleanup_free_ gid_t *peer_groups = NULL;
size_t n_test_gids;
uid_t test_uid;
gid_t test_gid;
@@ -472,25 +562,245 @@ static void test_getpeercred_getpeergroups(void) {
assert_se(ucred.gid == test_gid);
assert_se(ucred.pid == getpid_cached());
- r = getpeergroups(pair[0], &peer_groups);
- assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT));
+ {
+ _cleanup_free_ gid_t *peer_groups = NULL;
- if (r >= 0) {
- assert_se((size_t) r == n_test_gids);
- assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0);
+ r = getpeergroups(pair[0], &peer_groups);
+ assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT));
+
+ if (r >= 0) {
+ assert_se((size_t) r == n_test_gids);
+ assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0);
+ }
}
safe_close_pair(pair);
+ _exit(EXIT_SUCCESS);
}
}
-int main(int argc, char *argv[]) {
+static void test_passfd_read(void) {
+ static const char file_contents[] = "test contents for passfd";
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
+
+ r = safe_fork("(passfd_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* Child */
+ char tmpfile[] = "/tmp/test-socket-util-passfd-read-XXXXXX";
+ _cleanup_close_ int tmpfd = -1;
+
+ pair[0] = safe_close(pair[0]);
+
+ tmpfd = mkostemp_safe(tmpfile);
+ assert_se(tmpfd >= 0);
+ assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents));
+ tmpfd = safe_close(tmpfd);
+
+ tmpfd = open(tmpfile, O_RDONLY);
+ assert_se(tmpfd >= 0);
+ assert_se(unlink(tmpfile) == 0);
+
+ assert_se(send_one_fd(pair[1], tmpfd, MSG_DONTWAIT) == 0);
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* Parent */
+ char buf[64];
+ struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
+ _cleanup_close_ int fd = -1;
+
+ pair[1] = safe_close(pair[1]);
+
+ assert_se(receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd) == 0);
+
+ assert_se(fd >= 0);
+ r = read(fd, buf, sizeof(buf)-1);
+ assert_se(r >= 0);
+ buf[r] = 0;
+ assert_se(streq(buf, file_contents));
+}
+
+static void test_passfd_contents_read(void) {
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ static const char file_contents[] = "test contents in the file";
+ static const char wire_contents[] = "test contents on the wire";
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
+
+ r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* Child */
+ struct iovec iov = IOVEC_INIT_STRING(wire_contents);
+ char tmpfile[] = "/tmp/test-socket-util-passfd-contents-read-XXXXXX";
+ _cleanup_close_ int tmpfd = -1;
+
+ pair[0] = safe_close(pair[0]);
+
+ tmpfd = mkostemp_safe(tmpfile);
+ assert_se(tmpfd >= 0);
+ assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents));
+ tmpfd = safe_close(tmpfd);
+
+ tmpfd = open(tmpfile, O_RDONLY);
+ assert_se(tmpfd >= 0);
+ assert_se(unlink(tmpfile) == 0);
+
+ assert_se(send_one_fd_iov(pair[1], tmpfd, &iov, 1, MSG_DONTWAIT) > 0);
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* Parent */
+ char buf[64];
+ struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
+ _cleanup_close_ int fd = -1;
+ ssize_t k;
+
+ pair[1] = safe_close(pair[1]);
+
+ k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
+ assert_se(k > 0);
+ buf[k] = 0;
+ assert_se(streq(buf, wire_contents));
+
+ assert_se(fd >= 0);
+ r = read(fd, buf, sizeof(buf)-1);
+ assert_se(r >= 0);
+ buf[r] = 0;
+ assert_se(streq(buf, file_contents));
+}
+
+static void test_receive_nopassfd(void) {
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ static const char wire_contents[] = "no fd passed here";
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
+
+ r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* Child */
+ struct iovec iov = IOVEC_INIT_STRING(wire_contents);
+
+ pair[0] = safe_close(pair[0]);
+
+ assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) > 0);
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* Parent */
+ char buf[64];
+ struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
+ int fd = -999;
+ ssize_t k;
+
+ pair[1] = safe_close(pair[1]);
+
+ k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
+ assert_se(k > 0);
+ buf[k] = 0;
+ assert_se(streq(buf, wire_contents));
+
+ /* no fd passed here, confirm it was reset */
+ assert_se(fd == -1);
+}
+
+static void test_send_nodata_nofd(void) {
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ int r;
- log_set_max_level(LOG_DEBUG);
+ log_info("/* %s */", __func__);
+
+ assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
+
+ r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* Child */
+ pair[0] = safe_close(pair[0]);
+
+ assert_se(send_one_fd_iov(pair[1], -1, NULL, 0, MSG_DONTWAIT) == -EINVAL);
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* Parent */
+ char buf[64];
+ struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
+ int fd = -999;
+ ssize_t k;
+
+ pair[1] = safe_close(pair[1]);
+
+ k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
+ /* recvmsg() will return errno EAGAIN if nothing was sent */
+ assert_se(k == -EAGAIN);
+
+ /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */
+ assert_se(fd == -999);
+}
+
+static void test_send_emptydata(void) {
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
+
+ r = safe_fork("(send_emptydata)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* Child */
+ struct iovec iov = IOVEC_INIT_STRING(""); /* zero-length iov */
+ assert_se(iov.iov_len == 0);
+
+ pair[0] = safe_close(pair[0]);
+
+ /* This will succeed, since iov is set. */
+ assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) == 0);
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* Parent */
+ char buf[64];
+ struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
+ int fd = -999;
+ ssize_t k;
+
+ pair[1] = safe_close(pair[1]);
+
+ k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
+ /* receive_one_fd_iov() returns -EIO if an fd is not found and no data was returned. */
+ assert_se(k == -EIO);
+
+ /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */
+ assert_se(fd == -999);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
test_ifname_valid();
test_socket_address_parse();
+ test_socket_print_unix();
test_socket_address_parse_netlink();
test_socket_address_equal();
test_socket_address_get_path();
@@ -512,5 +822,11 @@ int main(int argc, char *argv[]) {
test_getpeercred_getpeergroups();
+ test_passfd_read();
+ test_passfd_contents_read();
+ test_receive_nopassfd();
+ test_send_nodata_nofd();
+ test_send_emptydata();
+
return 0;
}
diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c
index 9c7c352b51..a0ffdf6cb6 100644
--- a/src/test/test-specifier.c
+++ b/src/test/test-specifier.c
@@ -5,6 +5,7 @@
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
static void test_specifier_escape_one(const char *a, const char *b) {
_cleanup_free_ char *x = NULL;
@@ -39,7 +40,7 @@ static void test_specifier_escape_strv(void) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
test_specifier_escape();
test_specifier_escape_strv();
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index 39a7c499b3..4637a7f727 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -6,17 +6,18 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "hexdecoct.h"
#include "io-util.h"
#include "macro.h"
#include "path-util.h"
#include "rm-rf.h"
#include "missing.h"
-#include "mount-util.h"
+#include "mountpoint-util.h"
+#include "path-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
+#include "tmpfile-util.h"
static void test_files_same(void) {
_cleanup_close_ int fd = -1;
@@ -73,11 +74,101 @@ static void test_path_is_temporary_fs(void) {
assert_se(path_is_temporary_fs("/i-dont-exist") == -ENOENT);
}
+static void test_fd_is_network_ns(void) {
+ _cleanup_close_ int fd = -1;
+ assert_se(fd_is_network_ns(STDIN_FILENO) == 0);
+ assert_se(fd_is_network_ns(STDERR_FILENO) == 0);
+ assert_se(fd_is_network_ns(STDOUT_FILENO) == 0);
+
+ assert_se((fd = open("/proc/self/ns/mnt", O_CLOEXEC|O_RDONLY)) >= 0);
+ assert_se(IN_SET(fd_is_network_ns(fd), 0, -EUCLEAN));
+ fd = safe_close(fd);
+
+ assert_se((fd = open("/proc/self/ns/net", O_CLOEXEC|O_RDONLY)) >= 0);
+ assert_se(IN_SET(fd_is_network_ns(fd), 1, -EUCLEAN));
+}
+
+static void test_device_major_minor_valid(void) {
+ /* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */
+ assert_cc(sizeof(dev_t) == sizeof(uint64_t));
+
+ assert_se(DEVICE_MAJOR_VALID(0U));
+ assert_se(DEVICE_MINOR_VALID(0U));
+
+ assert_se(DEVICE_MAJOR_VALID(1U));
+ assert_se(DEVICE_MINOR_VALID(1U));
+
+ assert_se(!DEVICE_MAJOR_VALID(-1U));
+ assert_se(!DEVICE_MINOR_VALID(-1U));
+
+ assert_se(DEVICE_MAJOR_VALID(1U << 10));
+ assert_se(DEVICE_MINOR_VALID(1U << 10));
+
+ assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1));
+ assert_se(DEVICE_MINOR_VALID((1U << 20) - 1));
+
+ assert_se(!DEVICE_MAJOR_VALID((1U << 12)));
+ assert_se(!DEVICE_MINOR_VALID((1U << 20)));
+
+ assert_se(!DEVICE_MAJOR_VALID(1U << 25));
+ assert_se(!DEVICE_MINOR_VALID(1U << 25));
+
+ assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX));
+ assert_se(!DEVICE_MINOR_VALID(UINT32_MAX));
+
+ assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX));
+ assert_se(!DEVICE_MINOR_VALID(UINT64_MAX));
+
+ assert_se(DEVICE_MAJOR_VALID(major(0)));
+ assert_se(DEVICE_MINOR_VALID(minor(0)));
+}
+
+static void test_device_path_make_canonical_one(const char *path) {
+ _cleanup_free_ char *resolved = NULL, *raw = NULL;
+ struct stat st;
+ dev_t devno;
+ mode_t mode;
+ int r;
+
+ assert_se(stat(path, &st) >= 0);
+ r = device_path_make_canonical(st.st_mode, st.st_rdev, &resolved);
+ if (r == -ENOENT) /* maybe /dev/char/x:y and /dev/block/x:y are missing in this test environment, because we
+ * run in a container or so? */
+ return;
+
+ assert_se(r >= 0);
+ assert_se(path_equal(path, resolved));
+
+ assert_se(device_path_make_major_minor(st.st_mode, st.st_rdev, &raw) >= 0);
+ assert_se(device_path_parse_major_minor(raw, &mode, &devno) >= 0);
+
+ assert_se(st.st_rdev == devno);
+ assert_se((st.st_mode & S_IFMT) == (mode & S_IFMT));
+}
+
+static void test_device_path_make_canonical(void) {
+
+ test_device_path_make_canonical_one("/dev/null");
+ test_device_path_make_canonical_one("/dev/zero");
+ test_device_path_make_canonical_one("/dev/full");
+ test_device_path_make_canonical_one("/dev/random");
+ test_device_path_make_canonical_one("/dev/urandom");
+ test_device_path_make_canonical_one("/dev/tty");
+
+ if (is_device_node("/run/systemd/inaccessible/chr") > 0) {
+ test_device_path_make_canonical_one("/run/systemd/inaccessible/chr");
+ test_device_path_make_canonical_one("/run/systemd/inaccessible/blk");
+ }
+}
+
int main(int argc, char *argv[]) {
test_files_same();
test_is_symlink();
test_path_is_fs_type();
test_path_is_temporary_fs();
+ test_fd_is_network_ns();
+ test_device_major_minor_valid();
+ test_device_path_make_canonical();
return 0;
}
diff --git a/src/test/test-static-destruct.c b/src/test/test-static-destruct.c
new file mode 100644
index 0000000000..eb0523d87a
--- /dev/null
+++ b/src/test/test-static-destruct.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "static-destruct.h"
+#include "tests.h"
+
+static int foo = 0;
+static int bar = 0;
+static int baz = 0;
+static char* memory = NULL;
+
+static void test_destroy(int *b) {
+ (*b)++;
+}
+
+STATIC_DESTRUCTOR_REGISTER(foo, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(bar, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(bar, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(baz, test_destroy);
+STATIC_DESTRUCTOR_REGISTER(memory, freep);
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ assert_se(memory = strdup("hallo"));
+
+ assert_se(foo == 0 && bar == 0 && baz == 0);
+ static_destruct();
+ assert_se(foo == 1 && bar == 2 && baz == 3);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 3e72ce2c0a..8c1f91d4ef 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -5,6 +5,7 @@
#include "macro.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
#include "utf8.h"
static void test_string_erase(void) {
@@ -30,6 +31,64 @@ static void test_string_erase(void) {
assert_se(x[9] == '\0');
}
+static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) {
+ int r;
+
+ log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)",
+ __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change));
+
+ r = free_and_strndup(t, src, l);
+ assert_se(streq_ptr(*t, expected));
+ assert_se(r == change); /* check that change occurs only when necessary */
+}
+
+static void test_free_and_strndup(void) {
+ static const struct test_case {
+ const char *src;
+ size_t len;
+ const char *expected;
+ } cases[] = {
+ {"abc", 0, ""},
+ {"abc", 0, ""},
+ {"abc", 1, "a"},
+ {"abc", 2, "ab"},
+ {"abc", 3, "abc"},
+ {"abc", 4, "abc"},
+ {"abc", 5, "abc"},
+ {"abc", 5, "abc"},
+ {"abc", 4, "abc"},
+ {"abc", 3, "abc"},
+ {"abc", 2, "ab"},
+ {"abc", 1, "a"},
+ {"abc", 0, ""},
+
+ {"", 0, ""},
+ {"", 1, ""},
+ {"", 2, ""},
+ {"", 0, ""},
+ {"", 1, ""},
+ {"", 2, ""},
+ {"", 2, ""},
+ {"", 1, ""},
+ {"", 0, ""},
+
+ {NULL, 0, NULL},
+
+ {"foo", 3, "foo"},
+ {"foobar", 6, "foobar"},
+ };
+
+ _cleanup_free_ char *t = NULL;
+ const char *prev_expected = t;
+
+ for (unsigned i = 0; i < ELEMENTSOF(cases); i++) {
+ test_free_and_strndup_one(&t,
+ cases[i].src, cases[i].len, cases[i].expected,
+ !streq_ptr(cases[i].expected, prev_expected));
+ prev_expected = t;
+ }
+}
+
static void test_ascii_strcasecmp_n(void) {
assert_se(ascii_strcasecmp_n("", "", 0) == 0);
@@ -496,8 +555,34 @@ static void test_memory_startswith(void) {
assert_se(!memory_startswith("xxx", 4, "xxxx"));
}
+static void test_memory_startswith_no_case(void) {
+ assert_se(streq(memory_startswith_no_case("", 0, ""), ""));
+ assert_se(streq(memory_startswith_no_case("", 1, ""), ""));
+ assert_se(streq(memory_startswith_no_case("x", 2, ""), "x"));
+ assert_se(streq(memory_startswith_no_case("X", 2, ""), "X"));
+ assert_se(!memory_startswith_no_case("", 1, "X"));
+ assert_se(!memory_startswith_no_case("", 1, "xxxxXXXX"));
+ assert_se(streq(memory_startswith_no_case("xxx", 4, "X"), "xx"));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "x"), "XX"));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "X"), "XX"));
+ assert_se(streq(memory_startswith_no_case("xxx", 4, "XX"), "x"));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "xx"), "X"));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "XX"), "X"));
+ assert_se(streq(memory_startswith_no_case("xxx", 4, "XXX"), ""));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "xxx"), ""));
+ assert_se(streq(memory_startswith_no_case("XXX", 4, "XXX"), ""));
+
+ assert_se(memory_startswith_no_case((char[2]){'x', 'x'}, 2, "xx"));
+ assert_se(memory_startswith_no_case((char[2]){'x', 'X'}, 2, "xX"));
+ assert_se(memory_startswith_no_case((char[2]){'X', 'x'}, 2, "Xx"));
+ assert_se(memory_startswith_no_case((char[2]){'X', 'X'}, 2, "XX"));
+}
+
int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
test_string_erase();
+ test_free_and_strndup();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
test_cellescape();
@@ -525,6 +610,7 @@ int main(int argc, char *argv[]) {
test_first_word();
test_strlen_ptr();
test_memory_startswith();
+ test_memory_startswith_no_case();
return 0;
}
diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c
index 362f862221..fae384ef9b 100644
--- a/src/test/test-strip-tab-ansi.c
+++ b/src/test/test-strip-tab-ansi.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include "alloc-util.h"
+#include "pretty-print.h"
#include "string-util.h"
#include "terminal-util.h"
#include "util.h"
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index 1c192239a2..31ef1abb44 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -56,6 +56,20 @@ static void test_strptr_in_set(void) {
assert_se(!STRPTR_IN_SET(NULL, NULL));
}
+static void test_startswith_set(void) {
+ assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo"));
+ assert_se(!STARTSWITH_SET("foo", "bar"));
+
+ assert_se(STARTSWITH_SET("abc", "a", "ab", "abc"));
+ assert_se(STARTSWITH_SET("abc", "ax", "ab", "abc"));
+ assert_se(STARTSWITH_SET("abc", "ax", "abx", "abc"));
+ assert_se(!STARTSWITH_SET("abc", "ax", "abx", "abcx"));
+
+ assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "foo", "zzz"), "bar"));
+ assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "", "zzz"), "foobar"));
+ assert_se(streq_ptr(STARTSWITH_SET("", "hhh", "kkk", "zzz", ""), ""));
+}
+
static const char* const input_table_multiple[] = {
"one",
"two",
@@ -63,6 +77,13 @@ static const char* const input_table_multiple[] = {
NULL,
};
+static const char* const input_table_quoted[] = {
+ "one",
+ " two\t three ",
+ " four five",
+ NULL,
+};
+
static const char* const input_table_one[] = {
"one",
NULL,
@@ -144,6 +165,38 @@ static void test_strv_join(void) {
assert_se(streq(w, ""));
}
+static void test_strv_join_prefix(void) {
+ _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
+
+ p = strv_join_prefix((char **)input_table_multiple, ", ", "foo");
+ assert_se(p);
+ assert_se(streq(p, "fooone, footwo, foothree"));
+
+ q = strv_join_prefix((char **)input_table_multiple, ";", "foo");
+ assert_se(q);
+ assert_se(streq(q, "fooone;footwo;foothree"));
+
+ r = strv_join_prefix((char **)input_table_multiple, NULL, "foo");
+ assert_se(r);
+ assert_se(streq(r, "fooone footwo foothree"));
+
+ s = strv_join_prefix((char **)input_table_one, ", ", "foo");
+ assert_se(s);
+ assert_se(streq(s, "fooone"));
+
+ t = strv_join_prefix((char **)input_table_none, ", ", "foo");
+ assert_se(t);
+ assert_se(streq(t, ""));
+
+ v = strv_join_prefix((char **)input_table_two_empties, ", ", "foo");
+ assert_se(v);
+ assert_se(streq(v, "foo, foo"));
+
+ w = strv_join_prefix((char **)input_table_one_empty, ", ", "foo");
+ assert_se(w);
+ assert_se(streq(w, "foo"));
+}
+
static void test_strv_unquote(const char *quoted, char **list) {
_cleanup_strv_free_ char **s;
_cleanup_free_ char *j;
@@ -174,18 +227,127 @@ static void test_invalid_unquote(const char *quoted) {
}
static void test_strv_split(void) {
- char **s;
- unsigned i = 0;
_cleanup_strv_free_ char **l = NULL;
const char str[] = "one,two,three";
l = strv_split(str, ",");
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_multiple));
+
+ strv_free(l);
+ l = strv_split(" one two\t three", WHITESPACE);
assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_multiple));
- STRV_FOREACH(s, l) {
- assert_se(streq(*s, input_table_multiple[i++]));
- }
+ strv_free(l);
+
+ /* Setting NULL for separator is equivalent to WHITESPACE */
+ l = strv_split(" one two\t three", NULL);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_multiple));
+
+ strv_free(l);
+
+ l = strv_split_full(" one two\t three", NULL, 0);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_multiple));
+
+ strv_free(l);
+
+ l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_quoted));
+
+ strv_free(l);
+
+ /* missing last quote ignores the last element. */
+ l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_quoted));
+
+ strv_free(l);
+
+ /* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */
+ l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_quoted));
+
+ strv_free(l);
+
+ /* missing separator between */
+ l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_quoted));
+
+ strv_free(l);
+
+ l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
+ assert_se(l);
+ assert_se(strv_equal(l, (char**) input_table_quoted));
+}
+
+static void test_strv_split_empty(void) {
+ _cleanup_strv_free_ char **l = NULL;
+
+ l = strv_split("", WHITESPACE);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split("", NULL);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full("", NULL, 0);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full("", NULL, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full("", WHITESPACE, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split(" ", WHITESPACE);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split(" ", NULL);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full(" ", NULL, 0);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full(" ", NULL, SPLIT_QUOTES);
+ assert_se(l);
+ assert_se(strv_isempty(l));
+
+ strv_free(l);
+ l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX);
+ assert_se(l);
+ assert_se(strv_isempty(l));
}
static void test_strv_split_extract(void) {
@@ -233,18 +395,18 @@ static void test_strv_split_nulstr(void) {
static void test_strv_parse_nulstr(void) {
_cleanup_strv_free_ char **l = NULL;
- const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
+ const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx";
l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
assert_se(l);
puts("Parse nulstr:");
strv_print(l);
- assert_se(streq(l[0], "fuck"));
- assert_se(streq(l[1], "fuck2"));
- assert_se(streq(l[2], "fuck3"));
+ assert_se(streq(l[0], "hoge"));
+ assert_se(streq(l[1], "hoge2"));
+ assert_se(streq(l[2], "hoge3"));
assert_se(streq(l[3], ""));
- assert_se(streq(l[4], "fuck5"));
+ assert_se(streq(l[4], "hoge5"));
assert_se(streq(l[5], ""));
assert_se(streq(l[6], "xxx"));
}
@@ -293,8 +455,8 @@ static void test_strv_sort(void) {
static void test_strv_extend_strv_concat(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
- a = strv_new("without", "suffix", NULL);
- b = strv_new("with", "suffix", NULL);
+ a = strv_new("without", "suffix");
+ b = strv_new("with", "suffix");
assert_se(a);
assert_se(b);
@@ -309,8 +471,8 @@ static void test_strv_extend_strv_concat(void) {
static void test_strv_extend_strv(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL;
- a = strv_new("abc", "def", "ghi", NULL);
- b = strv_new("jkl", "mno", "abc", "pqr", NULL);
+ a = strv_new("abc", "def", "ghi");
+ b = strv_new("jkl", "mno", "abc", "pqr");
assert_se(a);
assert_se(b);
@@ -335,7 +497,7 @@ static void test_strv_extend_strv(void) {
static void test_strv_extend(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
- a = strv_new("test", "test1", NULL);
+ a = strv_new("test", "test1");
assert_se(a);
assert_se(strv_extend(&a, "test2") >= 0);
assert_se(strv_extend(&b, "test3") >= 0);
@@ -349,7 +511,7 @@ static void test_strv_extend(void) {
static void test_strv_extendf(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
- a = strv_new("test", "test1", NULL);
+ a = strv_new("test", "test1");
assert_se(a);
assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0);
@@ -365,7 +527,7 @@ static void test_strv_foreach(void) {
unsigned i = 0;
char **check;
- a = strv_new("one", "two", "three", NULL);
+ a = strv_new("one", "two", "three");
assert_se(a);
@@ -379,7 +541,7 @@ static void test_strv_foreach_backwards(void) {
unsigned i = 2;
char **check;
- a = strv_new("one", "two", "three", NULL);
+ a = strv_new("one", "two", "three");
assert_se(a);
@@ -399,8 +561,7 @@ static void test_strv_foreach_pair(void) {
a = strv_new("pair_one", "pair_one",
"pair_two", "pair_two",
- "pair_three", "pair_three",
- NULL);
+ "pair_three", "pair_three");
STRV_FOREACH_PAIR(x, y, a) {
assert_se(streq(*x, *y));
@@ -460,7 +621,7 @@ static void test_strv_insert(void) {
static void test_strv_push_prepend(void) {
_cleanup_strv_free_ char **a = NULL;
- a = strv_new("foo", "bar", "three", NULL);
+ a = strv_new("foo", "bar", "three");
assert_se(strv_push_prepend(&a, strdup("first")) >= 0);
assert_se(streq(a[0], "first"));
@@ -500,11 +661,11 @@ static void test_strv_equal(void) {
_cleanup_strv_free_ char **b = NULL;
_cleanup_strv_free_ char **c = NULL;
- a = strv_new("one", "two", "three", NULL);
+ a = strv_new("one", "two", "three");
assert_se(a);
- b = strv_new("one", "two", "three", NULL);
+ b = strv_new("one", "two", "three");
assert_se(a);
- c = strv_new("one", "two", "three", "four", NULL);
+ c = strv_new("one", "two", "three", "four");
assert_se(a);
assert_se(strv_equal(a, a));
@@ -519,19 +680,19 @@ static void test_strv_equal(void) {
static void test_strv_is_uniq(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
- a = strv_new(NULL, NULL);
+ a = strv_new(NULL);
assert_se(a);
assert_se(strv_is_uniq(a));
- b = strv_new("foo", NULL);
+ b = strv_new("foo");
assert_se(b);
assert_se(strv_is_uniq(b));
- c = strv_new("foo", "bar", NULL);
+ c = strv_new("foo", "bar");
assert_se(c);
assert_se(strv_is_uniq(c));
- d = strv_new("foo", "bar", "waldo", "bar", "piep", NULL);
+ d = strv_new("foo", "bar", "waldo", "bar", "piep");
assert_se(d);
assert_se(!strv_is_uniq(d));
}
@@ -539,26 +700,26 @@ static void test_strv_is_uniq(void) {
static void test_strv_reverse(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
- a = strv_new(NULL, NULL);
+ a = strv_new(NULL);
assert_se(a);
strv_reverse(a);
assert_se(strv_isempty(a));
- b = strv_new("foo", NULL);
+ b = strv_new("foo");
assert_se(b);
strv_reverse(b);
assert_se(streq_ptr(b[0], "foo"));
assert_se(streq_ptr(b[1], NULL));
- c = strv_new("foo", "bar", NULL);
+ c = strv_new("foo", "bar");
assert_se(c);
strv_reverse(c);
assert_se(streq_ptr(c[0], "bar"));
assert_se(streq_ptr(c[1], "foo"));
assert_se(streq_ptr(c[2], NULL));
- d = strv_new("foo", "bar", "waldo", NULL);
+ d = strv_new("foo", "bar", "waldo");
assert_se(d);
strv_reverse(d);
assert_se(streq_ptr(d[0], "waldo"));
@@ -570,7 +731,7 @@ static void test_strv_reverse(void) {
static void test_strv_shell_escape(void) {
_cleanup_strv_free_ char **v = NULL;
- v = strv_new("foo:bar", "bar,baz", "wal\\do", NULL);
+ v = strv_new("foo:bar", "bar,baz", "wal\\do");
assert_se(v);
assert_se(strv_shell_escape(v, ",:"));
assert_se(streq_ptr(v[0], "foo\\:bar"));
@@ -604,7 +765,7 @@ static void test_strv_skip(void) {
static void test_strv_extend_n(void) {
_cleanup_strv_free_ char **v = NULL;
- v = strv_new("foo", "bar", NULL);
+ v = strv_new("foo", "bar");
assert_se(v);
assert_se(strv_extend_n(&v, "waldo", 3) >= 0);
@@ -660,8 +821,8 @@ static void test_strv_free_free(void) {
char ***t;
assert_se(t = new(char**, 3));
- assert_se(t[0] = strv_new("a", "b", NULL));
- assert_se(t[1] = strv_new("c", "d", "e", NULL));
+ assert_se(t[0] = strv_new("a", "b"));
+ assert_se(t[1] = strv_new("c", "d", "e"));
t[2] = NULL;
t = strv_free_free(t);
@@ -691,7 +852,7 @@ static void test_strv_fnmatch(void) {
assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0));
- v = strv_new("*\\*", NULL);
+ v = strv_new("*\\*");
assert_se(!strv_fnmatch(v, "\\", 0));
assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE));
}
@@ -700,6 +861,7 @@ int main(int argc, char *argv[]) {
test_specifier_printf();
test_str_in_set();
test_strptr_in_set();
+ test_startswith_set();
test_strv_foreach();
test_strv_foreach_backwards();
test_strv_foreach_pair();
@@ -707,6 +869,7 @@ int main(int argc, char *argv[]) {
test_strv_find_prefix();
test_strv_find_startswith();
test_strv_join();
+ test_strv_join_prefix();
test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
test_strv_unquote("", STRV_MAKE_EMPTY);
@@ -733,6 +896,7 @@ int main(int argc, char *argv[]) {
test_invalid_unquote("'x'y'g");
test_strv_split();
+ test_strv_split_empty();
test_strv_split_extract();
test_strv_split_newlines();
test_strv_split_nulstr();
diff --git a/src/test/test-systemd-tmpfiles.py b/src/test/test-systemd-tmpfiles.py
index 13a44f3c4a..83a66e8772 100755
--- a/src/test/test-systemd-tmpfiles.py
+++ b/src/test/test-systemd-tmpfiles.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-# SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
#
-# 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 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.
import os
import sys
@@ -12,6 +12,7 @@ import socket
import subprocess
import tempfile
import pwd
+import grp
try:
from systemd import id128
@@ -95,9 +96,13 @@ def test_valid_specifiers(*, user):
test_content('f {} - - - - %H', '{}'.format(socket.gethostname()), user=user)
test_content('f {} - - - - %v', '{}'.format(os.uname().release), user=user)
test_content('f {} - - - - %U', '{}'.format(os.getuid()), user=user)
+ test_content('f {} - - - - %G', '{}'.format(os.getgid()), user=user)
- user = pwd.getpwuid(os.getuid())
- test_content('f {} - - - - %u', '{}'.format(user.pw_name), user=user)
+ puser = pwd.getpwuid(os.getuid())
+ test_content('f {} - - - - %u', '{}'.format(puser.pw_name), user=user)
+
+ pgroup = grp.getgrgid(os.getgid())
+ test_content('f {} - - - - %g', '{}'.format(pgroup.gr_name), user=user)
# Note that %h is the only specifier in which we look the environment,
# because we check $HOME. Should we even be doing that?
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 4c3b264989..bce7e3390a 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -6,6 +6,7 @@
#include "cgroup.h"
#include "compress.h"
#include "condition.h"
+#include "device-internal.h"
#include "device.h"
#include "execute.h"
#include "import-util.h"
@@ -25,6 +26,7 @@
#include "rlimit-util.h"
#include "scope.h"
#include "service.h"
+#include "show-status.h"
#include "slice.h"
#include "socket-util.h"
#include "socket.h"
@@ -51,7 +53,9 @@ int main(int argc, char **argv) {
test_table(collect_mode, COLLECT_MODE);
test_table(condition_result, CONDITION_RESULT);
test_table(condition_type, CONDITION_TYPE);
+ test_table(device_action, DEVICE_ACTION);
test_table(device_state, DEVICE_STATE);
+ test_table(dns_over_tls_mode, DNS_OVER_TLS_MODE);
test_table(dnssec_mode, DNSSEC_MODE);
test_table(emergency_action, EMERGENCY_ACTION);
test_table(exec_directory_type, EXEC_DIRECTORY_TYPE);
@@ -79,6 +83,7 @@ int main(int argc, char **argv) {
test_table(name_policy, NAMEPOLICY);
test_table(namespace_type, NAMESPACE_TYPE);
test_table(notify_access, NOTIFY_ACCESS);
+ test_table(notify_state, NOTIFY_STATE);
test_table(output_mode, OUTPUT_MODE);
test_table(partition_designator, PARTITION_DESIGNATOR);
test_table(path_result, PATH_RESULT);
@@ -95,6 +100,7 @@ int main(int argc, char **argv) {
test_table(service_result, SERVICE_RESULT);
test_table(service_state, SERVICE_STATE);
test_table(service_type, SERVICE_TYPE);
+ test_table(show_status, SHOW_STATUS);
test_table(slice_state, SLICE_STATE);
test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY);
test_table(socket_exec_command, SOCKET_EXEC_COMMAND);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index 9f27c74139..958d369430 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -5,11 +5,11 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
-#include "log.h"
#include "macro.h"
#include "strv.h"
#include "terminal-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "util.h"
static void test_default_term_for_tty(void) {
@@ -32,15 +32,11 @@ static void test_read_one_char(void) {
char r;
bool need_nl;
char name[] = "/tmp/test-read_one_char.XXXXXX";
- int fd;
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- file = fdopen(fd, "r+");
- assert_se(file);
+ assert(fmkostemp_safe(name, "r+", &file) == 0);
+
assert_se(fputs("c\n", file) >= 0);
rewind(file);
-
assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0);
assert_se(!need_nl);
assert_se(r == 'c');
@@ -59,36 +55,11 @@ static void test_read_one_char(void) {
unlink(name);
}
-static void test_terminal_urlify(void) {
- _cleanup_free_ char *formatted = NULL;
-
- assert_se(terminal_urlify("https://www.freedesktop.org/wiki/Software/systemd/", "systemd homepage", &formatted) >= 0);
- printf("Hey, considere visiting the %s right now! It is very good!\n", formatted);
-
- formatted = mfree(formatted);
-
- assert_se(terminal_urlify_path("/etc/fstab", "this link to your /etc/fstab", &formatted) >= 0);
- printf("Or click on %s to have a look at it!\n", formatted);
-}
-
-static void test_cat_files(void) {
- assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT);
- assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0);
-
- if (access("/etc/fstab", R_OK) >= 0)
- assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0);
-}
-
int main(int argc, char *argv[]) {
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
test_default_term_for_tty();
test_read_one_char();
- test_terminal_urlify();
- test_cat_files();
-
- print_separator();
return 0;
}
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
index 87de8d172c..2ec2ade3f1 100644
--- a/src/test/test-time-util.c
+++ b/src/test/test-time-util.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "random-util.h"
+#include "serialize.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -36,14 +37,37 @@ static void test_parse_sec(void) {
assert_se(u == USEC_INFINITY);
assert_se(parse_sec(" infinity ", &u) >= 0);
assert_se(u == USEC_INFINITY);
+ assert_se(parse_sec("+3.1s", &u) >= 0);
+ assert_se(u == 3100 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1s.2", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 .2", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 sec .2 sec", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 sec 1.2 sec", &u) >= 0);
+ assert_se(u == 4300 * USEC_PER_MSEC);
assert_se(parse_sec(" xyz ", &u) < 0);
assert_se(parse_sec("", &u) < 0);
assert_se(parse_sec(" . ", &u) < 0);
assert_se(parse_sec(" 5. ", &u) < 0);
assert_se(parse_sec(".s ", &u) < 0);
+ assert_se(parse_sec("-5s ", &u) < 0);
+ assert_se(parse_sec("-0.3s ", &u) < 0);
+ assert_se(parse_sec("-0.0s ", &u) < 0);
+ assert_se(parse_sec("-0.-0s ", &u) < 0);
+ assert_se(parse_sec("0.-0s ", &u) < 0);
+ assert_se(parse_sec("3.-0s ", &u) < 0);
assert_se(parse_sec(" infinity .7", &u) < 0);
assert_se(parse_sec(".3 infinity", &u) < 0);
+ assert_se(parse_sec("3.+1s", &u) < 0);
+ assert_se(parse_sec("3. 1s", &u) < 0);
+ assert_se(parse_sec("3.s", &u) < 0);
+ assert_se(parse_sec("12.34.56", &u) < 0);
+ assert_se(parse_sec("12..34", &u) < 0);
+ assert_se(parse_sec("..1234", &u) < 0);
+ assert_se(parse_sec("1234..", &u) < 0);
}
static void test_parse_sec_fix_0(void) {
@@ -54,7 +78,7 @@ static void test_parse_sec_fix_0(void) {
assert_se(parse_sec_fix_0("5s", &u) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_sec_fix_0("0s", &u) >= 0);
- assert_se(u == 0 * USEC_PER_SEC);
+ assert_se(u == USEC_INFINITY);
assert_se(parse_sec_fix_0("0", &u) >= 0);
assert_se(u == USEC_INFINITY);
assert_se(parse_sec_fix_0(" 0", &u) >= 0);
@@ -83,6 +107,9 @@ static void test_parse_time(void) {
assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
+
+ assert_se(parse_time("11111111111111y", &u, 1) == -ERANGE);
+ assert_se(parse_time("1.1111111111111y", &u, 1) >= 0);
}
static void test_parse_nsec(void) {
@@ -112,6 +139,16 @@ static void test_parse_nsec(void) {
assert_se(u == NSEC_INFINITY);
assert_se(parse_nsec(" infinity ", &u) >= 0);
assert_se(u == NSEC_INFINITY);
+ assert_se(parse_nsec("+3.1s", &u) >= 0);
+ assert_se(u == 3100 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1s.2", &u) >= 0);
+ assert_se(u == 3100 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1 .2s", &u) >= 0);
+ assert_se(u == 200 * NSEC_PER_MSEC + 3);
+ assert_se(parse_nsec("3.1 sec .2 sec", &u) >= 0);
+ assert_se(u == 3300 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1 sec 1.2 sec", &u) >= 0);
+ assert_se(u == 4300 * NSEC_PER_MSEC);
assert_se(parse_nsec(" xyz ", &u) < 0);
assert_se(parse_nsec("", &u) < 0);
@@ -120,6 +157,23 @@ static void test_parse_nsec(void) {
assert_se(parse_nsec(".s ", &u) < 0);
assert_se(parse_nsec(" infinity .7", &u) < 0);
assert_se(parse_nsec(".3 infinity", &u) < 0);
+ assert_se(parse_nsec("-5s ", &u) < 0);
+ assert_se(parse_nsec("-0.3s ", &u) < 0);
+ assert_se(parse_nsec("-0.0s ", &u) < 0);
+ assert_se(parse_nsec("-0.-0s ", &u) < 0);
+ assert_se(parse_nsec("0.-0s ", &u) < 0);
+ assert_se(parse_nsec("3.-0s ", &u) < 0);
+ assert_se(parse_nsec(" infinity .7", &u) < 0);
+ assert_se(parse_nsec(".3 infinity", &u) < 0);
+ assert_se(parse_nsec("3.+1s", &u) < 0);
+ assert_se(parse_nsec("3. 1s", &u) < 0);
+ assert_se(parse_nsec("3.s", &u) < 0);
+ assert_se(parse_nsec("12.34.56", &u) < 0);
+ assert_se(parse_nsec("12..34", &u) < 0);
+ assert_se(parse_nsec("..1234", &u) < 0);
+ assert_se(parse_nsec("1234..", &u) < 0);
+ assert_se(parse_nsec("1111111111111y", &u) == -ERANGE);
+ assert_se(parse_nsec("1.111111111111y", &u) >= 0);
}
static void test_format_timespan_one(usec_t x, usec_t accuracy) {
@@ -311,40 +365,40 @@ static void test_format_timestamp_utc(void) {
test_format_timestamp_utc_one(USEC_INFINITY, NULL);
}
-static void test_dual_timestamp_deserialize(void) {
+static void test_deserialize_dual_timestamp(void) {
int r;
dual_timestamp t;
log_info("/* %s */", __func__);
- r = dual_timestamp_deserialize("1234 5678", &t);
+ r = deserialize_dual_timestamp("1234 5678", &t);
assert_se(r == 0);
assert_se(t.realtime == 1234);
assert_se(t.monotonic == 5678);
- r = dual_timestamp_deserialize("1234x 5678", &t);
+ r = deserialize_dual_timestamp("1234x 5678", &t);
assert_se(r == -EINVAL);
- r = dual_timestamp_deserialize("1234 5678y", &t);
+ r = deserialize_dual_timestamp("1234 5678y", &t);
assert_se(r == -EINVAL);
- r = dual_timestamp_deserialize("-1234 5678", &t);
+ r = deserialize_dual_timestamp("-1234 5678", &t);
assert_se(r == -EINVAL);
- r = dual_timestamp_deserialize("1234 -5678", &t);
+ r = deserialize_dual_timestamp("1234 -5678", &t);
assert_se(r == -EINVAL);
/* Check that output wasn't modified. */
assert_se(t.realtime == 1234);
assert_se(t.monotonic == 5678);
- r = dual_timestamp_deserialize("+123 567", &t);
+ r = deserialize_dual_timestamp("+123 567", &t);
assert_se(r == 0);
assert_se(t.realtime == 123);
assert_se(t.monotonic == 567);
/* Check that we get "infinity" on overflow. */
- r = dual_timestamp_deserialize("18446744073709551617 0", &t);
+ r = deserialize_dual_timestamp("18446744073709551617 0", &t);
assert_se(r == 0);
assert_se(t.realtime == USEC_INFINITY);
assert_se(t.monotonic == 0);
@@ -432,7 +486,7 @@ int main(int argc, char *argv[]) {
test_usec_sub_unsigned();
test_format_timestamp();
test_format_timestamp_utc();
- test_dual_timestamp_deserialize();
+ test_deserialize_dual_timestamp();
test_usec_shift_clock();
test_in_utc_timezone();
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 3817790233..b526871655 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -13,6 +13,8 @@
#include "log.h"
#include "process-util.h"
#include "string-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "util.h"
int main(int argc, char** argv) {
@@ -21,8 +23,7 @@ int main(int argc, char** argv) {
const char *p = argv[1] ?: "/tmp";
char *pattern;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
pattern = strjoina(p, "/systemd-test-XXXXXX");
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index bed51c1270..7a4622b875 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -11,13 +11,16 @@
#include <sys/signalfd.h>
#include <unistd.h>
+#include "device-private.h"
#include "fs-util.h"
#include "log.h"
+#include "main-func.h"
#include "missing.h"
+#include "mkdir.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "string-util.h"
-#include "udev-util.h"
+#include "tests.h"
#include "udev.h"
static int fake_filesystems(void) {
@@ -27,106 +30,102 @@ static int fake_filesystems(void) {
const char *error;
bool ignore_mount_error;
} fakefss[] = {
- { "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 },
+ { "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;
+ unsigned i;
if (unshare(CLONE_NEWNS) < 0)
- return log_error_errno(errno, "failed to call unshare(): %m");
+ return log_error_errno(errno, "Failed to call unshare(): %m");
- if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
- return log_error_errno(errno, "failed to mount / as private: %m");
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
+ return log_error_errno(errno, "Failed to mount / as private: %m");
- for (i = 0; i < ELEMENTSOF(fakefss); i++) {
+ for (i = 0; i < ELEMENTSOF(fakefss); i++)
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;
}
- }
return 0;
}
-int main(int argc, char *argv[]) {
- _cleanup_(udev_unrefp) struct udev *udev = NULL;
- _cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
- _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
- _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
- char syspath[UTIL_PATH_SIZE];
- const char *devpath;
- const char *action;
- int err;
+static int run(int argc, char *argv[]) {
+ _cleanup_(udev_rules_freep) UdevRules *rules = NULL;
+ _cleanup_(udev_event_freep) UdevEvent *event = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ const char *devpath, *devname, *action;
+ int r;
+
+ test_setup_logging(LOG_INFO);
- log_parse_environment();
- log_open();
+ if (!IN_SET(argc, 2, 3)) {
+ log_error("This program needs one or two arguments, %d given", argc - 1);
+ return -EINVAL;
+ }
- err = fake_filesystems();
- if (err < 0)
- return EXIT_FAILURE;
+ r = fake_filesystems();
+ if (r < 0)
+ return r;
- udev = udev_new();
- if (udev == NULL)
- return EXIT_FAILURE;
+ if (argc == 2) {
+ if (!streq(argv[1], "check")) {
+ log_error("Unknown argument: %s", argv[1]);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
log_debug("version %s", PACKAGE_VERSION);
mac_selinux_init();
action = argv[1];
- if (action == NULL) {
- log_error("action missing");
- goto out;
- }
-
devpath = argv[2];
- if (devpath == NULL) {
- log_error("devpath missing");
- goto out;
- }
- rules = udev_rules_new(udev, 1);
+ assert_se(udev_rules_new(&rules, RESOLVE_NAME_EARLY) == 0);
- strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
- dev = udev_device_new_from_synthetic_event(udev, syspath, action);
- if (dev == NULL) {
- log_debug("unknown device '%s'", devpath);
- goto out;
- }
+ const char *syspath = strjoina("/sys", devpath);
+ r = device_new_from_synthetic_event(&dev, syspath, action);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to open device '%s'", devpath);
- event = udev_event_new(dev);
+ assert_se(event = udev_event_new(dev, 0, NULL));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
/* do what devtmpfs usually provides us */
- if (udev_device_get_devnode(dev) != NULL) {
+ if (sd_device_get_devname(dev, &devname) >= 0) {
+ const char *subsystem;
mode_t mode = 0600;
- if (streq(udev_device_get_subsystem(dev), "block"))
+ if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block"))
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (!streq(action, "remove")) {
- mkdir_parents_label(udev_device_get_devnode(dev), 0755);
- mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
+ dev_t devnum = makedev(0, 0);
+
+ (void) mkdir_parents_label(devname, 0755);
+ (void) sd_device_get_devnum(dev, &devnum);
+ if (mknod(devname, mode, devnum) < 0)
+ return log_error_errno(errno, "mknod() failed for '%s': %m", devname);
} else {
- unlink(udev_device_get_devnode(dev));
- rmdir_parents(udev_device_get_devnode(dev), "/");
+ if (unlink(devname) < 0)
+ return log_error_errno(errno, "unlink('%s') failed: %m", devname);
+ (void) rmdir_parents(devname, "/");
}
}
- udev_event_execute_rules(event,
- 3 * USEC_PER_SEC, USEC_PER_SEC,
- NULL,
- rules);
- udev_event_execute_run(event,
- 3 * USEC_PER_SEC, USEC_PER_SEC);
-out:
- mac_selinux_finish();
+ udev_event_execute_rules(event, 3 * USEC_PER_SEC, NULL, rules);
+ udev_event_execute_run(event, 3 * USEC_PER_SEC);
- return err ? EXIT_FAILURE : EXIT_SUCCESS;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/src/test/test-umount.c b/src/test/test-umount.c
index 770d1a73c8..6ab5758ede 100644
--- a/src/test/test-umount.c
+++ b/src/test/test-umount.c
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include "alloc-util.h"
#include "log.h"
+#include "path-util.h"
#include "string-util.h"
#include "tests.h"
#include "umount.h"
@@ -8,10 +10,14 @@
static void test_mount_points_list(const char *fname) {
_cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
+ _cleanup_free_ char *testdata_fname = NULL;
MountPoint *m;
log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo");
+ if (fname)
+ fname = testdata_fname = path_join(get_testdata_dir(), fname);
+
LIST_HEAD_INIT(mp_list_head);
assert_se(mount_points_list_get(fname, &mp_list_head) >= 0);
@@ -26,10 +32,14 @@ static void test_mount_points_list(const char *fname) {
static void test_swap_list(const char *fname) {
_cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
+ _cleanup_free_ char *testdata_fname = NULL;
MountPoint *m;
log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/swaps");
+ if (fname)
+ fname = testdata_fname = path_join(get_testdata_dir(), fname);
+
LIST_HEAD_INIT(mp_list_head);
assert_se(swap_list_get(fname, &mp_list_head) >= 0);
@@ -43,15 +53,13 @@ static void test_swap_list(const char *fname) {
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_mount_points_list(NULL);
- test_mount_points_list(get_testdata_dir("/test-umount/empty.mountinfo"));
- test_mount_points_list(get_testdata_dir("/test-umount/garbled.mountinfo"));
- test_mount_points_list(get_testdata_dir("/test-umount/rhbug-1554943.mountinfo"));
+ test_mount_points_list("/test-umount/empty.mountinfo");
+ test_mount_points_list("/test-umount/garbled.mountinfo");
+ test_mount_points_list("/test-umount/rhbug-1554943.mountinfo");
test_swap_list(NULL);
- test_swap_list(get_testdata_dir("/test-umount/example.swaps"));
+ test_swap_list("/test-umount/example.swaps");
}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 09b0179fa1..f5578f9fc2 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -7,12 +7,12 @@
#include <sys/capability.h>
#include <unistd.h>
-#include "alloc-util.h"
#include "all-units.h"
+#include "alloc-util.h"
#include "capability-util.h"
#include "conf-parser.h"
+#include "env-file.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "hashmap.h"
#include "hostname-util.h"
@@ -26,6 +26,7 @@
#include "strv.h"
#include "test-helper.h"
#include "tests.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
@@ -39,11 +40,8 @@ static int test_unit_file_get_set(void) {
assert_se(h);
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
-
- if (IN_SET(r, -EPERM, -EACCES)) {
- log_notice_errno(r, "Skipping test: unit_file_get_list: %m");
- return EXIT_TEST_SKIP;
- }
+ if (IN_SET(r, -EPERM, -EACCES))
+ return log_tests_skipped_errno(r, "unit_file_get_list");
log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
"unit_file_get_list: %m");
@@ -532,9 +530,9 @@ static void test_load_env_file_1(void) {
fd = mkostemp_safe(name);
assert_se(fd >= 0);
- assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
+ assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1));
- r = load_env_file(NULL, name, NULL, &data);
+ r = load_env_file(NULL, name, &data);
assert_se(r == 0);
assert_se(streq(data[0], "a=a"));
assert_se(streq(data[1], "b=bc"));
@@ -554,9 +552,9 @@ static void test_load_env_file_2(void) {
fd = mkostemp_safe(name);
assert_se(fd >= 0);
- assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
+ assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2));
- r = load_env_file(NULL, name, NULL, &data);
+ r = load_env_file(NULL, name, &data);
assert_se(r == 0);
assert_se(streq(data[0], "a=a"));
assert_se(data[1] == NULL);
@@ -571,9 +569,9 @@ static void test_load_env_file_3(void) {
fd = mkostemp_safe(name);
assert_se(fd >= 0);
- assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
+ assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3));
- r = load_env_file(NULL, name, NULL, &data);
+ r = load_env_file(NULL, name, &data);
assert_se(r == 0);
assert_se(data == NULL);
}
@@ -586,9 +584,9 @@ static void test_load_env_file_4(void) {
fd = mkostemp_safe(name);
assert_se(fd >= 0);
- assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
+ assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4));
- r = load_env_file(NULL, name, NULL, &data);
+ r = load_env_file(NULL, name, &data);
assert_se(r == 0);
assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
assert_se(streq(data[1], "MODULE_0=coretemp"));
@@ -605,9 +603,9 @@ static void test_load_env_file_5(void) {
fd = mkostemp_safe(name);
assert_se(fd >= 0);
- assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
+ assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5));
- r = load_env_file(NULL, name, NULL, &data);
+ r = load_env_file(NULL, name, &data);
assert_se(r == 0);
assert_se(streq(data[0], "a="));
assert_se(streq(data[1], "b="));
@@ -624,11 +622,13 @@ static void test_install_printf(void) {
UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
- _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = 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(group = gid_to_name(getgid()));
+ assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0);
assert_se(user = uid_to_name(getuid()));
assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
@@ -655,6 +655,8 @@ static void test_install_printf(void) {
expect(i, "%p", "name");
expect(i, "%i", "");
expect(i, "%j", "name");
+ expect(i, "%g", group);
+ expect(i, "%G", gid);
expect(i, "%u", user);
expect(i, "%U", uid);
@@ -662,12 +664,16 @@ static void test_install_printf(void) {
expect(i, "%b", bid);
expect(i, "%H", host);
+ expect(i2, "%g", group);
+ expect(i2, "%G", gid);
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, "%g", group);
+ expect(i3, "%G", gid);
expect(i3, "%u", user);
expect(i3, "%U", uid);
@@ -675,6 +681,8 @@ static void test_install_printf(void) {
expect(i3, "%b", bid);
expect(i3, "%H", host);
+ expect(i4, "%g", group);
+ expect(i4, "%G", gid);
expect(i4, "%u", user);
expect(i4, "%U", uid);
}
@@ -896,14 +904,11 @@ int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r;
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice_errno(r, "Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir());
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 2b00ef8cb7..2afae22510 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -191,7 +191,7 @@ static void test_unit_name_mangle(void) {
}
static int test_unit_printf(void) {
- _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
+ _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
Unit *u;
int r;
@@ -200,15 +200,15 @@ static int test_unit_printf(void) {
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
assert_se(host = gethostname_malloc());
assert_se(user = uid_to_name(getuid()));
+ assert_se(group = gid_to_name(getgid()));
assert_se(asprintf(&uid, UID_FMT, getuid()));
+ assert_se(asprintf(&gid, UID_FMT, getgid()));
assert_se(get_home_dir(&home) >= 0);
assert_se(get_shell(&shell) >= 0);
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
- if (MANAGER_SKIP_TEST(r)) {
- log_notice_errno(r, "Skipping test: manager_new: %m");
- return EXIT_TEST_SKIP;
- }
+ if (MANAGER_SKIP_TEST(r))
+ return log_tests_skipped_errno(r, "manager_new");
assert_se(r == 0);
#define expect(unit, pattern, expected) \
@@ -243,6 +243,8 @@ static int test_unit_printf(void) {
expect(u, "%I", "");
expect(u, "%j", "blah");
expect(u, "%J", "blah");
+ expect(u, "%g", group);
+ expect(u, "%G", gid);
expect(u, "%u", user);
expect(u, "%U", uid);
expect(u, "%h", home);
@@ -265,6 +267,8 @@ static int test_unit_printf(void) {
expect(u, "%I", "foo/foo");
expect(u, "%j", "blah");
expect(u, "%J", "blah");
+ expect(u, "%g", group);
+ expect(u, "%G", gid);
expect(u, "%u", user);
expect(u, "%U", uid);
expect(u, "%h", home);
@@ -528,7 +532,6 @@ static void test_unit_name_from_dbus_path(void) {
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/accounts_2ddaemon_2eservice", 0, "accounts-daemon.service");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/auditd_2eservice", 0, "auditd.service");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/basic_2etarget", 0, "basic.target");
- test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/bluetooth_2etarget", 0, "bluetooth.target");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2eautomount", 0, "boot.automount");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2emount", 0, "boot.mount");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/btrfs_2emount", 0, "btrfs.mount");
@@ -811,14 +814,11 @@ int main(int argc, char* argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r, rc = 0;
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice_errno(r, "Skipping test: cgroupfs not available");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir());
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index c1428fab02..801824ad67 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -159,7 +159,7 @@ static void test_get_user_creds_one(const char *id, const char *name, uid_t uid,
log_info("/* %s(\"%s\", \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\") */",
__func__, id, name, uid, gid, home, shell);
- r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell);
+ r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell, 0);
log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m",
id, ruid, rgid, strnull(rhome), strnull(rshell));
if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) {
@@ -180,7 +180,7 @@ static void test_get_group_creds_one(const char *id, const char *name, gid_t gid
log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid);
- r = get_group_creds(&id, &rgid);
+ r = get_group_creds(&id, &rgid, 0);
log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid);
if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
log_info("(skipping detailed tests because nobody is not synthesized)");
@@ -191,7 +191,7 @@ static void test_get_group_creds_one(const char *id, const char *name, gid_t gid
assert_se(rgid == gid);
}
-int main(int argc, char*argv[]) {
+int main(int argc, char *argv[]) {
test_uid_to_name_one(0, "root");
test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
test_uid_to_name_one(0xFFFF, "65535");
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index fe3db314a0..9849530ac8 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -1,10 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Dave Reisner
-***/
#include "alloc-util.h"
#include "string-util.h"
+#include "strv.h"
#include "utf8.h"
#include "util.h"
@@ -90,15 +88,25 @@ static void test_utf8_escaping_printable(void) {
}
static void test_utf16_to_utf8(void) {
- char *a = NULL;
- const uint16_t utf16[] = { htole16('a'), htole16(0xd800), htole16('b'), htole16(0xdc00), htole16('c'), htole16(0xd801), htole16(0xdc37) };
- const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7, 0 };
+ const char16_t utf16[] = { htole16('a'), htole16(0xd800), htole16('b'), htole16(0xdc00), htole16('c'), htole16(0xd801), htole16(0xdc37) };
+ static const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7 };
+ _cleanup_free_ char16_t *b = NULL;
+ _cleanup_free_ char *a = NULL;
- a = utf16_to_utf8(utf16, 14);
+ /* Convert UTF-16 to UTF-8, filtering embedded bad chars */
+ a = utf16_to_utf8(utf16, sizeof(utf16));
assert_se(a);
- assert_se(streq(a, utf8));
+ assert_se(memcmp(a, utf8, sizeof(utf8)) == 0);
+
+ /* Convert UTF-8 to UTF-16, and back */
+ b = utf8_to_utf16(utf8, sizeof(utf8));
+ assert_se(b);
free(a);
+ a = utf16_to_utf8(b, char16_strlen(b) * 2);
+ assert_se(a);
+ assert_se(strlen(a) == sizeof(utf8));
+ assert_se(memcmp(a, utf8, sizeof(utf8)) == 0);
}
static void test_utf8_n_codepoints(void) {
@@ -119,6 +127,28 @@ static void test_utf8_console_width(void) {
assert_se(utf8_console_width("\xF1") == (size_t) -1);
}
+static void test_utf8_to_utf16(void) {
+ const char *p;
+
+ FOREACH_STRING(p,
+ "abc",
+ "zażółcić gęślą jaźń",
+ "串",
+ "",
+ "…👊🔪💐…") {
+
+ _cleanup_free_ char16_t *a = NULL;
+ _cleanup_free_ char *b = NULL;
+
+ a = utf8_to_utf16(p, strlen(p));
+ assert_se(a);
+
+ b = utf16_to_utf8(a, char16_strlen(a) * 2);
+ assert_se(b);
+ assert_se(streq(p, b));
+ }
+}
+
int main(int argc, char *argv[]) {
test_utf8_is_valid();
test_utf8_is_printable();
@@ -130,6 +160,7 @@ int main(int argc, char *argv[]) {
test_utf16_to_utf8();
test_utf8_n_codepoints();
test_utf8_console_width();
+ test_utf8_to_utf16();
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 4d3e5c5b94..3c1b5f9b41 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -8,16 +8,20 @@
#include "def.h"
#include "fileio.h"
#include "fs-util.h"
+#include "missing_syscall.h"
#include "parse-util.h"
#include "process-util.h"
#include "raw-clone.h"
#include "rm-rf.h"
#include "string-util.h"
+#include "tests.h"
#include "util.h"
static void test_align_power2(void) {
unsigned long i, p2;
+ log_info("/* %s */", __func__);
+
assert_se(ALIGN_POWER2(0) == 0);
assert_se(ALIGN_POWER2(1) == 1);
assert_se(ALIGN_POWER2(2) == 2);
@@ -53,6 +57,14 @@ static void test_max(void) {
.a = CONST_MAX(10, 100),
};
int d = 0;
+ unsigned long x = 12345;
+ unsigned long y = 54321;
+ const char str[] = "a_string_constant";
+ const unsigned long long arr[] = {9999ULL, 10ULL, 0ULL, 3000ULL, 2000ULL, 1000ULL, 100ULL, 9999999ULL};
+ void *p = (void *)str;
+ void *q = (void *)&str[16];
+
+ log_info("/* %s */", __func__);
assert_cc(sizeof(val1.b) == sizeof(int) * 100);
@@ -80,6 +92,35 @@ static void test_max(void) {
assert_se(LESS_BY(4, 8) == 0);
assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
+ assert_se(CMP(3, 5) == -1);
+ assert_se(CMP(5, 3) == 1);
+ assert_se(CMP(5, 5) == 0);
+ assert_se(CMP(x, y) == -1);
+ assert_se(CMP(y, x) == 1);
+ assert_se(CMP(x, x) == 0);
+ assert_se(CMP(y, y) == 0);
+ assert_se(CMP(UINT64_MAX, (uint64_t) 0) == 1);
+ assert_se(CMP((uint64_t) 0, UINT64_MAX) == -1);
+ assert_se(CMP(UINT64_MAX, UINT64_MAX) == 0);
+ assert_se(CMP(INT64_MIN, INT64_MAX) == -1);
+ assert_se(CMP(INT64_MAX, INT64_MIN) == 1);
+ assert_se(CMP(INT64_MAX, INT64_MAX) == 0);
+ assert_se(CMP(INT64_MIN, INT64_MIN) == 0);
+ assert_se(CMP(INT64_MAX, (int64_t) 0) == 1);
+ assert_se(CMP((int64_t) 0, INT64_MIN) == 1);
+ assert_se(CMP(INT64_MIN, (int64_t) 0) == -1);
+ assert_se(CMP((int64_t) 0, INT64_MAX) == -1);
+ assert_se(CMP(&str[2], &str[7]) == -1);
+ assert_se(CMP(&str[2], &str[2]) == 0);
+ assert_se(CMP(&str[7], (const char *)str) == 1);
+ assert_se(CMP(str[2], str[7]) == 1);
+ assert_se(CMP(str[7], *str) == 1);
+ assert_se(CMP((const unsigned long long *)arr, &arr[3]) == -1);
+ assert_se(CMP(*arr, arr[3]) == 1);
+ assert_se(CMP(p, q) == -1);
+ assert_se(CMP(q, p) == 1);
+ assert_se(CMP(p, p) == 0);
+ assert_se(CMP(q, q) == 0);
assert_se(CLAMP(-5, 0, 1) == 0);
assert_se(CLAMP(5, 0, 1) == 1);
assert_se(CLAMP(5, -10, 1) == 1);
@@ -100,6 +141,8 @@ static void test_container_of(void) {
uint32_t v2;
} _packed_ myval = { };
+ log_info("/* %s */", __func__);
+
assert_cc(sizeof(myval) == 17);
assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
@@ -115,6 +158,8 @@ static void test_container_of(void) {
static void test_div_round_up(void) {
int div;
+ log_info("/* %s */", __func__);
+
/* basic tests */
assert_se(DIV_ROUND_UP(0, 8) == 0);
assert_se(DIV_ROUND_UP(1, 8) == 1);
@@ -146,6 +191,8 @@ static void test_div_round_up(void) {
}
static void test_u64log2(void) {
+ log_info("/* %s */", __func__);
+
assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3);
assert_se(u64log2(9) == 3);
@@ -156,6 +203,8 @@ static void test_u64log2(void) {
}
static void test_protect_errno(void) {
+ log_info("/* %s */", __func__);
+
errno = 12;
{
PROTECT_ERRNO;
@@ -165,6 +214,8 @@ static void test_protect_errno(void) {
}
static void test_in_set(void) {
+ log_info("/* %s */", __func__);
+
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
assert_se(IN_SET(2, 1, 2, 3, 4));
@@ -175,6 +226,8 @@ static void test_in_set(void) {
}
static void test_log2i(void) {
+ log_info("/* %s */", __func__);
+
assert_se(log2i(1) == 0);
assert_se(log2i(2) == 1);
assert_se(log2i(3) == 1);
@@ -185,9 +238,25 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
+static void test_eqzero(void) {
+ const uint32_t zeros[] = {0, 0, 0};
+ const uint32_t ones[] = {1, 1};
+ const uint32_t mixed[] = {0, 1, 0, 0, 0};
+ const uint8_t longer[] = {[55] = 255};
+
+ log_info("/* %s */", __func__);
+
+ assert_se(eqzero(zeros));
+ assert_se(!eqzero(ones));
+ assert_se(!eqzero(mixed));
+ assert_se(!eqzero(longer));
+}
+
static void test_raw_clone(void) {
pid_t parent, pid, pid2;
+ log_info("/* %s */", __func__);
+
parent = getpid();
log_info("before clone: getpid()→"PID_FMT, parent);
assert_se(raw_getpid() == parent);
@@ -218,6 +287,8 @@ static void test_physical_memory(void) {
uint64_t p;
char buf[FORMAT_BYTES_MAX];
+ log_info("/* %s */", __func__);
+
p = physical_memory();
assert_se(p > 0);
assert_se(p < UINT64_MAX);
@@ -229,6 +300,8 @@ static void test_physical_memory(void) {
static void test_physical_memory_scale(void) {
uint64_t p;
+ log_info("/* %s */", __func__);
+
p = physical_memory();
assert_se(physical_memory_scale(0, 100) == 0);
@@ -263,6 +336,8 @@ static void test_physical_memory_scale(void) {
static void test_system_tasks_max(void) {
uint64_t t;
+ log_info("/* %s */", __func__);
+
t = system_tasks_max();
assert_se(t > 0);
assert_se(t < UINT64_MAX);
@@ -273,6 +348,8 @@ static void test_system_tasks_max(void) {
static void test_system_tasks_max_scale(void) {
uint64_t t;
+ log_info("/* %s */", __func__);
+
t = system_tasks_max();
assert_se(system_tasks_max_scale(0, 100) == 0);
@@ -298,8 +375,7 @@ static void test_system_tasks_max_scale(void) {
}
int main(int argc, char *argv[]) {
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
test_align_power2();
test_max();
@@ -309,6 +385,7 @@ int main(int argc, char *argv[]) {
test_protect_errno();
test_in_set();
test_log2i();
+ test_eqzero();
test_raw_clone();
test_physical_memory();
test_physical_memory_scale();
diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c
index cb43b35bc5..2c6ca0a1a2 100644
--- a/src/test/test-watch-pid.c
+++ b/src/test/test-watch-pid.c
@@ -13,25 +13,18 @@ int main(int argc, char *argv[]) {
Unit *a, *b, *c, *u;
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
-
- if (getuid() != 0) {
- log_notice("Not running as root, skipping kernel related tests.");
- return EXIT_TEST_SKIP;
- }
+ test_setup_logging(LOG_DEBUG);
+ if (getuid() != 0)
+ return log_tests_skipped("not root");
r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM) {
- log_notice("cgroupfs not available, skipping tests");
- return EXIT_TEST_SKIP;
- }
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
- assert_se(set_unit_path(get_testdata_dir("")) >= 0);
+ assert_se(set_unit_path(get_testdata_dir()) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
- assert_se(manager_new(UNIT_FILE_USER, true, &m) >= 0);
+ assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
assert_se(a = unit_new(m, sizeof(Service)));
diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c
index 2aba3b5a26..ab66d5c49d 100644
--- a/src/test/test-watchdog.c
+++ b/src/test/test-watchdog.c
@@ -3,8 +3,8 @@
#include <string.h>
#include <unistd.h>
-#include "env-util.h"
#include "log.h"
+#include "tests.h"
#include "watchdog.h"
int main(int argc, char *argv[]) {
@@ -13,11 +13,9 @@ int main(int argc, char *argv[]) {
int r;
bool slow;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
- r = getenv_bool("SYSTEMD_SLOW_TESTS");
- slow = r >= 0 ? r : SYSTEMD_SLOW_TESTS_DEFAULT;
+ slow = slow_tests_enabled();
t = slow ? 10 * USEC_PER_SEC : 1 * USEC_PER_SEC;
count = slow ? 5 : 3;
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
index 72720dccb8..3e6df96c5d 100644
--- a/src/test/test-xattr-util.c
+++ b/src/test/test-xattr-util.c
@@ -8,10 +8,11 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "macro.h"
#include "string-util.h"
+#include "tests.h"
+#include "tmpfile-util.h"
#include "xattr-util.h"
static void test_fgetxattrat_fake(void) {
@@ -78,9 +79,7 @@ static void test_getcrtime(void) {
}
int main(void) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_fgetxattrat_fake();
test_getcrtime();