summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-03-27 09:27:11 +0100
committerAdrian Szyndela <adrian.s@samsung.com>2020-03-27 11:13:45 +0100
commit5f3f628ebc0867b7d078849c614958e09ce74850 (patch)
treee6cabc7e68ae658b13db8857d3c308de691f73db /src/test
parent31e58df2dbd9a3b2afcebd654cc1ad29589dd6c0 (diff)
parentefb536d0cbe2e58f80e501d19999928c75e08f6a (diff)
downloadsystemd-5f3f628ebc0867b7d078849c614958e09ce74850.tar.gz
systemd-5f3f628ebc0867b7d078849c614958e09ce74850.tar.bz2
systemd-5f3f628ebc0867b7d078849c614958e09ce74850.zip
Merge v243 into tizen
systemd v243
Diffstat (limited to 'src/test')
-rwxr-xr-xsrc/test/generate-sym-test.py12
-rw-r--r--src/test/meson.build56
-rw-r--r--src/test/test-alloc-util.c80
-rw-r--r--src/test/test-ask-password-api.c1
-rw-r--r--src/test/test-bpf.c60
-rw-r--r--src/test/test-btrfs.c2
-rw-r--r--src/test/test-calendarspec.c9
-rw-r--r--src/test/test-capability.c2
-rw-r--r--src/test/test-cgroup-mask.c1
-rw-r--r--src/test/test-cgroup-unit-default.c145
-rw-r--r--src/test/test-cgroup-util.c2
-rw-r--r--src/test/test-chase-symlinks.c109
-rw-r--r--src/test/test-condition.c127
-rw-r--r--src/test/test-conf-files.c12
-rw-r--r--src/test/test-conf-parser.c19
-rw-r--r--src/test/test-copy.c14
-rw-r--r--src/test/test-cpu-set-util.c306
-rw-r--r--src/test/test-engine.c29
-rw-r--r--src/test/test-env-file.c143
-rw-r--r--src/test/test-env-util.c8
-rw-r--r--src/test/test-escape.c44
-rw-r--r--src/test/test-exec-util.c53
-rw-r--r--src/test/test-execute.c85
-rw-r--r--src/test/test-exit-status.c52
-rw-r--r--src/test/test-extract-word.c78
-rw-r--r--src/test/test-fileio.c15
-rw-r--r--src/test/test-format-table.c12
-rw-r--r--src/test/test-format-util.c39
-rw-r--r--src/test/test-fs-util.c51
-rw-r--r--src/test/test-hashmap-plain.c88
-rw-r--r--src/test/test-hashmap.c64
-rw-r--r--src/test/test-id128.c2
-rw-r--r--src/test/test-install-root.c2
-rw-r--r--src/test/test-journal-importer.c4
-rw-r--r--src/test/test-json.c7
-rw-r--r--src/test/test-libmount.c5
-rw-r--r--src/test/test-libudev.c46
-rw-r--r--src/test/test-load-fragment.c801
-rw-r--r--src/test/test-local-addresses.c44
-rw-r--r--src/test/test-log.c11
-rw-r--r--src/test/test-ns.c3
-rw-r--r--src/test/test-nss.c5
-rw-r--r--src/test/test-path-lookup.c6
-rw-r--r--src/test/test-path-util.c69
-rw-r--r--src/test/test-pretty-print.c2
-rw-r--r--src/test/test-proc-cmdline.c1
-rw-r--r--src/test/test-process-util.c147
-rw-r--r--src/test/test-procfs-util.c2
-rw-r--r--src/test/test-seccomp.c2
-rw-r--r--src/test/test-sizeof.c3
-rw-r--r--src/test/test-sleep.c40
-rw-r--r--src/test/test-socket-util.c62
-rw-r--r--src/test/test-string-util.c43
-rw-r--r--src/test/test-strv.c115
-rw-r--r--src/test/test-strxcpyx.c21
-rwxr-xr-xsrc/test/test-systemd-tmpfiles.py4
-rw-r--r--src/test/test-terminal-util.c33
-rw-r--r--src/test/test-udev.c2
-rw-r--r--src/test/test-umask-util.c41
-rw-r--r--src/test/test-unit-file.c980
-rw-r--r--src/test/test-unit-name.c13
-rw-r--r--src/test/test-user-util.c105
-rw-r--r--src/test/test-utf8.c62
-rw-r--r--src/test/test-varlink.c239
64 files changed, 3219 insertions, 1421 deletions
diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py
index 357cce8e44..4d358b8e34 100755
--- a/src/test/generate-sym-test.py
+++ b/src/test/generate-sym-test.py
@@ -6,18 +6,22 @@ for header in sys.argv[2:]:
print('#include "{}"'.format(header.split('/')[-1]))
print('''
-void* functions[] = {''')
+const void* symbols[] = {''')
for line in open(sys.argv[1]):
match = re.search('^ +([a-zA-Z0-9_]+);', line)
if match:
- print(' {},'.format(match.group(1)))
+ s = match.group(1)
+ if s == 'sd_bus_object_vtable_format':
+ print(' &{},'.format(s))
+ else:
+ print(' {},'.format(s))
print('''};
int main(void) {
unsigned i;
- for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
- printf("%p\\n", functions[i]);
+ for (i = 0; i < sizeof(symbols)/sizeof(void*); i++)
+ printf("%p\\n", symbols[i]);
return 0;
}''')
diff --git a/src/test/meson.build b/src/test/meson.build
index 660febccaa..7709993c05 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -137,6 +137,10 @@ tests += [
[],
'ENABLE_EFI'],
+ [['src/test/test-unit-file.c'],
+ [],
+ []],
+
[['src/test/test-unit-name.c',
'src/test/test-helper.c'],
[libcore,
@@ -148,7 +152,7 @@ tests += [
libmount,
libblkid]],
- [['src/test/test-unit-file.c',
+ [['src/test/test-load-fragment.c',
'src/test/test-helper.c'],
[libcore,
libshared],
@@ -216,6 +220,10 @@ tests += [
[],
[]],
+ [['src/test/test-format-util.c'],
+ [],
+ []],
+
[['src/test/test-ratelimit.c'],
[],
[]],
@@ -269,6 +277,10 @@ tests += [
[],
[]],
+ [['src/test/test-umask-util.c'],
+ [],
+ []],
+
[['src/test/test-proc-cmdline.c'],
[],
[]],
@@ -297,6 +309,10 @@ tests += [
[],
[]],
+ [['src/test/test-exit-status.c'],
+ [],
+ []],
+
[['src/test/test-specifier.c'],
[],
[]],
@@ -574,6 +590,12 @@ tests += [
libshared],
[]],
+ [['src/test/test-cgroup-unit-default.c',
+ 'src/test/test-helper.c'],
+ [libcore,
+ libshared],
+ []],
+
[['src/test/test-cgroup-mask.c',
'src/test/test-helper.c'],
[libcore,
@@ -585,10 +607,18 @@ tests += [
libmount,
libblkid]],
+ [['src/test/test-varlink.c'],
+ [],
+ [threads]],
+
[['src/test/test-cgroup-util.c'],
[],
[]],
+ [['src/test/test-env-file.c'],
+ [],
+ []],
+
[['src/test/test-env-util.c'],
[],
[]],
@@ -605,6 +635,11 @@ tests += [
[],
[]],
+ [['src/test/test-chase-symlinks.c'],
+ [],
+ [],
+ '', 'manual'],
+
[['src/test/test-path.c',
'src/test/test-helper.c'],
[libcore,
@@ -732,6 +767,10 @@ tests += [
[['src/test/test-sd-hwdb.c'],
[],
[]],
+
+ [['src/test/test-local-addresses.c'],
+ [],
+ []],
]
############################################################
@@ -905,7 +944,8 @@ tests += [
[],
[threads]],
- [['src/libsystemd/sd-bus/test-bus-vtable.c'],
+ [['src/libsystemd/sd-bus/test-bus-vtable.c',
+ 'src/libsystemd/sd-bus/test-vtable-data.h'],
[],
[]],
@@ -939,7 +979,8 @@ tests += [
[],
[]],
- [['src/libsystemd/sd-bus/test-bus-introspect.c'],
+ [['src/libsystemd/sd-bus/test-bus-introspect.c',
+ 'src/libsystemd/sd-bus/test-vtable-data.h'],
[],
[]],
@@ -951,10 +992,6 @@ tests += [
[],
[]],
- [['src/libsystemd/sd-netlink/test-local-addresses.c'],
- [],
- []],
-
[['src/libsystemd/sd-resolve/test-resolve.c'],
[],
[threads],
@@ -986,7 +1023,10 @@ tests += [
]
-if cxx_cmd != ''
+# test-bus-vtable-cc.cc is a symlink and symlinks get lost in containers on FuzzBuzz.
+# The issue has been reported to the developers of FuzzBuzz and hopefully will be fixed soon.
+# In the meantime, let's just skip the symlink there.
+if cxx_cmd != '' and not want_fuzzbuzz
tests += [
[['src/libsystemd/sd-bus/test-bus-vtable-cc.cc'],
[],
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
index ad10eb178a..758b753237 100644
--- a/src/test/test-alloc-util.c
+++ b/src/test/test-alloc-util.c
@@ -1,10 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <malloc.h>
#include <stdint.h>
#include "alloc-util.h"
#include "macro.h"
#include "memory-util.h"
+#include "random-util.h"
+#include "tests.h"
static void test_alloca(void) {
static const uint8_t zero[997] = { };
@@ -21,38 +24,52 @@ static void test_alloca(void) {
static void test_GREEDY_REALLOC(void) {
_cleanup_free_ int *a = NULL, *b = NULL;
- size_t n_allocated = 0, i;
+ size_t n_allocated = 0, i, j;
- /* Give valgrind a chance to verify our realloc operations */
+ /* Give valgrind a chance to verify our realloc() operations */
- for (i = 0; i < 2048; i++) {
+ for (i = 0; i < 20480; i++) {
assert_se(GREEDY_REALLOC(a, n_allocated, i + 1));
- a[i] = i;
+ assert_se(n_allocated >= i + 1);
+ assert_se(malloc_usable_size(a) >= (i + 1) * sizeof(int));
+ a[i] = (int) i;
assert_se(GREEDY_REALLOC(a, n_allocated, i / 2));
+ assert_se(n_allocated >= i / 2);
+ assert_se(malloc_usable_size(a) >= (i / 2) * sizeof(int));
}
- for (i = 30, n_allocated = 0; i < 2048; i+=7) {
+ for (j = 0; j < i / 2; j++)
+ assert_se(a[j] == (int) j);
+
+ for (i = 30, n_allocated = 0; i < 20480; i += 7) {
assert_se(GREEDY_REALLOC(b, n_allocated, i + 1));
- b[i] = i;
+ assert_se(n_allocated >= i + 1);
+ assert_se(malloc_usable_size(b) >= (i + 1) * sizeof(int));
+ b[i] = (int) i;
assert_se(GREEDY_REALLOC(b, n_allocated, i / 2));
+ assert_se(n_allocated >= i / 2);
+ assert_se(malloc_usable_size(b) >= (i / 2) * sizeof(int));
}
+
+ for (j = 30; j < i / 2; j += 7)
+ assert_se(b[j] == (int) j);
}
static void test_memdup_multiply_and_greedy_realloc(void) {
- int org[] = {1, 2, 3};
+ static const int org[] = { 1, 2, 3 };
_cleanup_free_ int *dup;
int *p;
size_t i, allocated = 3;
- dup = (int*) memdup_suffix0_multiply(org, sizeof(int), 3);
+ dup = memdup_suffix0_multiply(org, sizeof(int), 3);
assert_se(dup);
assert_se(dup[0] == 1);
assert_se(dup[1] == 2);
assert_se(dup[2] == 3);
- assert_se(*(uint8_t*) (dup + 3) == (uint8_t) 0);
+ assert_se(((uint8_t*) dup)[sizeof(int) * 3] == 0);
free(dup);
- dup = (int*) memdup_multiply(org, sizeof(int), 3);
+ dup = memdup_multiply(org, sizeof(int), 3);
assert_se(dup);
assert_se(dup[0] == 1);
assert_se(dup[1] == 2);
@@ -91,11 +108,54 @@ static void test_bool_assign(void) {
assert(!h);
}
+static int cleanup_counter = 0;
+
+static void cleanup1(void *a) {
+ log_info("%s(%p)", __func__, a);
+ assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup2(void *a) {
+ log_info("%s(%p)", __func__, a);
+ assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup3(void *a) {
+ log_info("%s(%p)", __func__, a);
+ assert_se(++cleanup_counter == *(int*) a);
+}
+
+static void test_cleanup_order(void) {
+ _cleanup_(cleanup1) int x1 = 4, x2 = 3;
+ _cleanup_(cleanup3) int z = 2;
+ _cleanup_(cleanup2) int y = 1;
+ log_debug("x1: %p", &x1);
+ log_debug("x2: %p", &x2);
+ log_debug("y: %p", &y);
+ log_debug("z: %p", &z);
+}
+
+static void test_auto_erase_memory(void) {
+ _cleanup_(erase_and_freep) uint8_t *p1, *p2;
+
+ assert_se(p1 = new(uint8_t, 1024));
+ assert_se(p2 = new(uint8_t, 1024));
+
+ assert_se(genuine_random_bytes(p1, 1024, RANDOM_BLOCK) == 0);
+
+ /* before we exit the scope, do something with this data, so that the compiler won't optimize this away */
+ memcpy(p2, p1, 1024);
+ for (size_t i = 0; i < 1024; i++)
+ assert_se(p1[i] == p2[i]);
+}
+
int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
test_alloca();
test_GREEDY_REALLOC();
test_memdup_multiply_and_greedy_realloc();
test_bool_assign();
+ test_cleanup_order();
+ test_auto_erase_memory();
return 0;
}
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
index 23b06be19b..fa91869cf5 100644
--- a/src/test/test-ask-password-api.c
+++ b/src/test/test-ask-password-api.c
@@ -20,4 +20,5 @@ int main(int argc, char **argv) {
log_parse_environment();
ask_password();
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c
index 6a0bf1462f..6a75221542 100644
--- a/src/test/test-bpf.c
+++ b/src/test/test-bpf.c
@@ -9,11 +9,13 @@
#include "bpf-program.h"
#include "load-fragment.h"
#include "manager.h"
+#include "missing.h"
#include "rm-rf.h"
#include "service.h"
#include "test-helper.h"
#include "tests.h"
#include "unit.h"
+#include "virt.h"
/* We use the same limit here that PID 1 bumps RLIMIT_MEMLOCK to if it can */
#define CAN_MEMLOCK_SIZE (64U*1024U*1024U)
@@ -41,7 +43,7 @@ static bool can_memlock(void) {
int main(int argc, char *argv[]) {
struct bpf_insn exit_insn[] = {
- BPF_MOV64_IMM(BPF_REG_0, 1),
+ BPF_MOV64_IMM(BPF_REG_0, 0), /* drop */
BPF_EXIT_INSN()
};
@@ -53,11 +55,14 @@ int main(int argc, char *argv[]) {
char log_buf[65535];
struct rlimit rl;
int r;
+ union bpf_attr attr;
+ bool test_custom_filter = false;
+ const char *test_prog = "/sys/fs/bpf/test-dropper";
test_setup_logging(LOG_DEBUG);
- if (is_run_on_travis_ci())
- return log_tests_skipped("test-bpf fails on Travis CI: https://github.com/systemd/systemd/issues/9666");
+ if (detect_container() > 0)
+ return log_tests_skipped("test-bpf fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666");
assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
rl.rlim_cur = rl.rlim_max = MAX3(rl.rlim_cur, rl.rlim_max, CAN_MEMLOCK_SIZE);
@@ -87,17 +92,34 @@ int main(int argc, char *argv[]) {
return log_tests_skipped("BPF firewalling not supported");
assert_se(r > 0);
- if (r == BPF_FIREWALL_SUPPORTED_WITH_MULTI)
+ if (r == BPF_FIREWALL_SUPPORTED_WITH_MULTI) {
log_notice("BPF firewalling with BPF_F_ALLOW_MULTI supported. Yay!");
- else
+ test_custom_filter = true;
+ } else
log_notice("BPF firewalling (though without BPF_F_ALLOW_MULTI) supported. Good.");
r = bpf_program_load_kernel(p, log_buf, ELEMENTSOF(log_buf));
assert(r >= 0);
+ if (test_custom_filter) {
+ attr = (union bpf_attr) {
+ .pathname = PTR_TO_UINT64(test_prog),
+ .bpf_fd = p->kernel_fd,
+ .file_flags = 0,
+ };
+
+ (void) unlink(test_prog);
+
+ r = bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+ if (r < 0) {
+ log_warning_errno(errno, "BPF object pinning failed, will not run custom filter test: %m");
+ test_custom_filter = false;
+ }
+ }
+
p = bpf_program_unref(p);
- /* The simple tests suceeded. Now let's try full unit-based use-case. */
+ /* The simple tests succeeded. Now let's try full unit-based use-case. */
assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
@@ -174,5 +196,31 @@ int main(int argc, char *argv[]) {
assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.code != CLD_EXITED ||
SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.status != EXIT_SUCCESS);
+ if (test_custom_filter) {
+ assert_se(u = unit_new(m, sizeof(Service)));
+ assert_se(unit_add_name(u, "custom-filter.service") == 0);
+ assert_se(cc = unit_get_cgroup_context(u));
+ u->perpetual = true;
+
+ cc->ip_accounting = true;
+
+ assert_se(config_parse_ip_filter_bpf_progs(u->id, "filename", 1, "Service", 1, "IPIngressFilterPath", 0, test_prog, &cc->ip_filters_ingress, u) == 0);
+ assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "-/bin/ping -c 1 127.0.0.1 -W 5", SERVICE(u)->exec_command, u) == 0);
+
+ SERVICE(u)->type = SERVICE_ONESHOT;
+ u->load_state = UNIT_LOADED;
+
+ assert_se(unit_start(u) >= 0);
+
+ while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED))
+ assert_se(sd_event_run(m->event, UINT64_MAX) >= 0);
+
+ assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.code != CLD_EXITED ||
+ SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.status != EXIT_SUCCESS);
+
+ (void) unlink(test_prog);
+ assert_se(SERVICE(u)->state == SERVICE_DEAD);
+ }
+
return 0;
}
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index 5e5638cd72..5bd0e3458c 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -5,8 +5,8 @@
#include "btrfs-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "format-util.h"
#include "log.h"
-#include "parse-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 10c9f63b9b..46358ef952 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "calendarspec.h"
+#include "errno-util.h"
#include "string-util.h"
#include "util.h"
@@ -23,7 +24,7 @@ static void test_one(const char *input, const char *output) {
u = now(CLOCK_REALTIME);
r = calendar_spec_next_usec(c, u, &u);
- printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
+ printf("Next: %s\n", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof(buf), u));
calendar_spec_free(c);
assert_se(calendar_spec_from_string(p, &c) >= 0);
@@ -56,7 +57,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_
u = after;
r = calendar_spec_next_usec(c, after, &u);
- printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u));
+ printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u));
if (expect != (usec_t)-1)
assert_se(r >= 0 && u == expect);
else
@@ -103,10 +104,10 @@ static void test_hourly_bug_4031(void) {
assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0);
printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n);
- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u), u);
assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0);
- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(zaf, sizeof zaf, w), w);
assert_se(n < u);
assert_se(u <= n + USEC_PER_HOUR);
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index 6b2de66bb7..f9fae84dde 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -99,7 +99,7 @@ static int setup_tests(bool *run_ambient) {
nobody = getpwnam(NOBODY_USER_NAME);
if (!nobody)
- return log_error_errno(errno, "Could not find nobody user: %m");
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Could not find nobody user: %m");
test_uid = nobody->pw_uid;
test_gid = nobody->pw_gid;
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index 7f6c0c2772..72a6551ffd 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -59,7 +59,6 @@ static int test_cgroup_mask(void) {
m->default_tasks_accounting = false;
m->default_tasks_max = (uint64_t) -1;
- assert_se(r >= 0);
assert_se(manager_startup(m, NULL, NULL) >= 0);
/* Load units and verify hierarchy. */
diff --git a/src/test/test-cgroup-unit-default.c b/src/test/test-cgroup-unit-default.c
new file mode 100644
index 0000000000..4fb629217f
--- /dev/null
+++ b/src/test/test-cgroup-unit-default.c
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio.h>
+
+#include "cgroup.h"
+#include "manager.h"
+#include "rm-rf.h"
+#include "test-helper.h"
+#include "tests.h"
+#include "unit.h"
+
+static int test_default_memory_low(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ Unit *root, *dml,
+ *dml_passthrough, *dml_passthrough_empty, *dml_passthrough_set_dml, *dml_passthrough_set_ml,
+ *dml_override, *dml_override_empty,
+ *dml_discard, *dml_discard_empty, *dml_discard_set_ml;
+ uint64_t dml_tree_default;
+ int r;
+
+ r = enter_cgroup_subroot();
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
+
+ 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)) {
+ log_error_errno(r, "manager_new: %m");
+ return log_tests_skipped("cannot create manager");
+ }
+
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ /* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this:
+ *
+ * 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only
+ * DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with
+ * memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which
+ * should have the value of 0, as it has MemoryLow explicitly set.
+ *
+ * ┌───────────┐
+ * │ dml.slice │
+ * └─────┬─────┘
+ * MemoryLow=100
+ * ┌───────────┴───────────┐
+ * │ dml-passthrough.slice │
+ * └───────────┬───────────┘
+ * ┌───────────────────────────────────┼───────────────────────────────────┐
+ * no new settings DefaultMemoryLow=15 MemoryLow=0
+ * ┌───────────────┴───────────────┐ ┌────────────────┴────────────────┐ ┌───────────────┴────────────────┐
+ * │ dml-passthrough-empty.service │ │ dml-passthrough-set-dml.service │ │ dml-passthrough-set-ml.service │
+ * └───────────────────────────────┘ └─────────────────────────────────┘ └────────────────────────────────┘
+ *
+ * 2. dml-override.slice sets DefaultMemoryLow=10. As such, dml-override-empty.service should also
+ * end up with a memory.low of 10. dml-override.slice should still have a memory.low of 50.
+ *
+ * ┌───────────┐
+ * │ dml.slice │
+ * └─────┬─────┘
+ * DefaultMemoryLow=10
+ * ┌─────────┴──────────┐
+ * │ dml-override.slice │
+ * └─────────┬──────────┘
+ * no new settings
+ * ┌─────────────┴──────────────┐
+ * │ dml-override-empty.service │
+ * └────────────────────────────┘
+ *
+ * 3. dml-discard.slice sets DefaultMemoryLow= with no rvalue. As such,
+ * dml-discard-empty.service should end up with a value of 0.
+ * dml-discard-explicit-ml.service sets MemoryLow=70, and as such should have that override the
+ * reset DefaultMemoryLow value. dml-discard.slice should still have an eventual memory.low of 50.
+ *
+ * ┌───────────┐
+ * │ dml.slice │
+ * └─────┬─────┘
+ * DefaultMemoryLow=
+ * ┌─────────┴─────────┐
+ * │ dml-discard.slice │
+ * └─────────┬─────────┘
+ * ┌──────────────┴───────────────┐
+ * no new settings MemoryLow=15
+ * ┌─────────────┴─────────────┐ ┌─────────────┴──────────────┐
+ * │ dml-discard-empty.service │ │ dml-discard-set-ml.service │
+ * └───────────────────────────┘ └────────────────────────────┘
+ */
+ assert_se(manager_load_startable_unit_or_warn(m, "dml.slice", NULL, &dml) >= 0);
+
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough.slice", NULL, &dml_passthrough) >= 0);
+ assert_se(UNIT_DEREF(dml_passthrough->slice) == dml);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-empty.service", NULL, &dml_passthrough_empty) >= 0);
+ assert_se(UNIT_DEREF(dml_passthrough_empty->slice) == dml_passthrough);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-dml.service", NULL, &dml_passthrough_set_dml) >= 0);
+ assert_se(UNIT_DEREF(dml_passthrough_set_dml->slice) == dml_passthrough);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-ml.service", NULL, &dml_passthrough_set_ml) >= 0);
+ assert_se(UNIT_DEREF(dml_passthrough_set_ml->slice) == dml_passthrough);
+
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-override.slice", NULL, &dml_override) >= 0);
+ assert_se(UNIT_DEREF(dml_override->slice) == dml);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-override-empty.service", NULL, &dml_override_empty) >= 0);
+ assert_se(UNIT_DEREF(dml_override_empty->slice) == dml_override);
+
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-discard.slice", NULL, &dml_discard) >= 0);
+ assert_se(UNIT_DEREF(dml_discard->slice) == dml);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-empty.service", NULL, &dml_discard_empty) >= 0);
+ assert_se(UNIT_DEREF(dml_discard_empty->slice) == dml_discard);
+ assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-set-ml.service", NULL, &dml_discard_set_ml) >= 0);
+ assert_se(UNIT_DEREF(dml_discard_set_ml->slice) == dml_discard);
+
+ root = UNIT_DEREF(dml->slice);
+ assert_se(!UNIT_ISSET(root->slice));
+
+ assert_se(unit_get_ancestor_memory_low(root) == CGROUP_LIMIT_MIN);
+
+ assert_se(unit_get_ancestor_memory_low(dml) == CGROUP_LIMIT_MIN);
+ dml_tree_default = unit_get_cgroup_context(dml)->default_memory_low;
+ assert_se(dml_tree_default == 50);
+
+ assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100);
+ assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default);
+ assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50);
+ assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0);
+
+ assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default);
+ assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10);
+
+ assert_se(unit_get_ancestor_memory_low(dml_discard) == dml_tree_default);
+ assert_se(unit_get_ancestor_memory_low(dml_discard_empty) == CGROUP_LIMIT_MIN);
+ assert_se(unit_get_ancestor_memory_low(dml_discard_set_ml) == 15);
+
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ int rc = EXIT_SUCCESS;
+
+ test_setup_logging(LOG_DEBUG);
+
+ TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low());
+
+ return rc;
+}
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index a3239d73f5..b54b5e76c6 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -341,7 +341,7 @@ static void test_is_wanted_print(bool header) {
log_info("cmdline: %s", cmdline);
if (header) {
- log_info(_CGROUP_HIEARCHY_);
+ log_info(_CGROUP_HIERARCHY_);
(void) system("findmnt -n /sys/fs/cgroup");
}
diff --git a/src/test/test-chase-symlinks.c b/src/test/test-chase-symlinks.c
new file mode 100644
index 0000000000..013b36e2a7
--- /dev/null
+++ b/src/test/test-chase-symlinks.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <getopt.h>
+
+#include "fd-util.h"
+#include "fs-util.h"
+#include "log.h"
+#include "main-func.h"
+
+static char *arg_root = NULL;
+static int arg_flags = 0;
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_ROOT = 0x1000,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "root", required_argument, NULL, ARG_ROOT },
+
+ { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT },
+ { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT },
+ { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS },
+ { "safe", no_argument, NULL, CHASE_SAFE },
+ { "open", no_argument, NULL, CHASE_OPEN },
+ { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH },
+ { "step", no_argument, NULL, CHASE_STEP },
+ { "nofollow", no_argument, NULL, CHASE_NOFOLLOW },
+ { "warn", no_argument, NULL, CHASE_WARN },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
+ switch (c) {
+
+ case 'h':
+ printf("Syntax:\n"
+ " %s [OPTION...] path...\n"
+ "Options:\n"
+ , argv[0]);
+ for (size_t i = 0; i < ELEMENTSOF(options) - 1; i++)
+ printf(" --%s\n", options[i].name);
+ return 0;
+
+ case ARG_ROOT:
+ arg_root = optarg;
+ break;
+
+ case CHASE_PREFIX_ROOT:
+ case CHASE_NONEXISTENT:
+ case CHASE_NO_AUTOFS:
+ case CHASE_SAFE:
+ case CHASE_OPEN:
+ case CHASE_TRAIL_SLASH:
+ case CHASE_STEP:
+ case CHASE_NOFOLLOW:
+ case CHASE_WARN:
+ arg_flags |= c;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (optind == argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At least one argument is required.");
+
+ return 1;
+}
+
+static int run(int argc, char **argv) {
+ int r;
+
+ log_show_color(true);
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ for (int i = optind; i < argc; i++) {
+ _cleanup_free_ char *p = NULL;
+
+ printf("%s ", argv[i]);
+ fflush(stdout);
+
+ r = chase_symlinks(argv[i], arg_root, arg_flags, &p);
+ if (r < 0)
+ log_error_errno(r, "failed: %m");
+ else
+ log_info("→ %s", p);
+
+ if (FLAGS_SET(arg_flags, CHASE_OPEN))
+ safe_close(r);
+ }
+
+ return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 2a5e3aba80..a79263a50b 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -13,6 +13,7 @@
#include "audit-util.h"
#include "cgroup-util.h"
#include "condition.h"
+#include "cpu-set-util.h"
#include "efivars.h"
#include "hostname-util.h"
#include "id128-util.h"
@@ -42,77 +43,77 @@ static void test_condition_test_path(void) {
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
}
@@ -132,12 +133,12 @@ static void test_condition_test_control_group_controller(void) {
/* Invalid controllers are ignored */
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
assert_se(cg_mask_supported(&system_mask) >= 0);
@@ -150,23 +151,23 @@ static void test_condition_test_control_group_controller(void) {
log_info("this controller is available");
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
} else {
log_info("this controller is unavailable");
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
}
}
@@ -176,12 +177,12 @@ static void test_condition_test_control_group_controller(void) {
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
}
@@ -217,17 +218,17 @@ static void test_condition_test_host(void) {
condition = condition_new(CONDITION_HOST, sid, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_HOST, sid, false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
hostname = gethostname_malloc();
@@ -239,7 +240,7 @@ static void test_condition_test_host(void) {
else {
condition = condition_new(CONDITION_HOST, hostname, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
}
}
@@ -276,12 +277,12 @@ static void test_condition_test_kernel_command_line(void) {
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
}
@@ -292,24 +293,26 @@ static void test_condition_test_kernel_version(void) {
condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
+ /* An artificially empty condition. It evaluates to true, but normally
+ * such condition cannot be created, because the condition list is reset instead. */
condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
assert_se(uname(&u) >= 0);
condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
strshorten(u.release, 4);
@@ -317,59 +320,79 @@ static void test_condition_test_kernel_version(void) {
condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
/* 0.1.2 would be a very very very old kernel */
condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) > 0);
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) > 0);
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) == -EINVAL);
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) == -EINVAL);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
/* 4711.8.15 is a very very very future kernel */
condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
assert_se(uname(&u) >= 0);
@@ -377,31 +400,31 @@ static void test_condition_test_kernel_version(void) {
v = strjoina(">=", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
v = strjoina("= ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
v = strjoina("<=", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
v = strjoina("> ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
v = strjoina("< ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
}
@@ -410,12 +433,12 @@ static void test_condition_test_null(void) {
condition = condition_new(CONDITION_NULL, NULL, false, false);
assert_se(condition);
- assert_se(condition_test(condition));
+ assert_se(condition_test(condition) > 0);
condition_free(condition);
condition = condition_new(CONDITION_NULL, NULL, false, true);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
}
@@ -424,7 +447,7 @@ static void test_condition_test_security(void) {
condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false);
assert_se(condition);
- assert_se(!condition_test(condition));
+ assert_se(condition_test(condition) == 0);
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 9fd8b6b590..61811311f4 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -30,7 +30,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
while (files) {
_cleanup_free_ char *path;
- assert_se(path = strappend(tmp_dir, files));
+ assert_se(path = path_join(tmp_dir, files));
(void) mkdir_parents(path, 0755);
assert_se(write_string_file(path, "foobar", WRITE_STRING_FILE_CREATE) >= 0);
@@ -102,11 +102,11 @@ static void test_conf_files_insert(const char *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");
+ *foo1 = path_join(root, "/dir1/foo.conf"),
+ *foo2 = path_join(root, "/dir2/foo.conf"),
+ *bar2 = path_join(root, "/dir2/bar.conf"),
+ *zzz3 = path_join(root, "/dir3/zzz.conf"),
+ *whatever = path_join(root, "/whatever.conf");
assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
assert_se(strv_equal(s, STRV_MAKE(foo2)));
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index 1738938fce..597265efa6 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -231,6 +231,13 @@ static const char* const config_file[] = {
"setting1=1\n", /* repeated settings */
"[Section]\n"
+ "[Section]\n"
+ "setting1=1\n"
+ "setting1=2\\\n"
+ " \n" /* empty line breaks continuation */
+ "setting1=1\n", /* repeated settings */
+
+ "[Section]\n"
"setting1=1\\\n" /* normal continuation */
"2\\\n"
"3\n",
@@ -330,32 +337,32 @@ static void test_config_parse(unsigned i, const char *s) {
CONFIG_PARSE_WARN, NULL);
switch (i) {
- case 0 ... 3:
+ case 0 ... 4:
assert_se(r == 0);
assert_se(streq(setting1, "1"));
break;
- case 4 ... 9:
+ case 5 ... 10:
assert_se(r == 0);
assert_se(streq(setting1, "1 2 3"));
break;
- case 10:
+ case 11:
assert_se(r == 0);
assert_se(streq(setting1, "1\\\\ \\\\2"));
break;
- case 11:
+ case 12:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD")));
break;
- case 12 ... 13:
+ case 13 ... 14:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD") " foobar"));
break;
- case 14 ... 15:
+ case 15 ... 16:
assert_se(r == -ENOBUFS);
assert_se(setting1 == NULL);
break;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 5f4bc39580..5f7b9e5ce8 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -52,8 +52,8 @@ static void test_copy_file_fd(void) {
char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
_cleanup_close_ int in_fd = -1, out_fd = -1;
- char text[] = "boohoo\nfoo\n\tbar\n";
- char buf[64] = {0};
+ const char *text = "boohoo\nfoo\n\tbar\n";
+ char buf[64] = {};
log_info("%s", __func__);
@@ -67,7 +67,7 @@ static void test_copy_file_fd(void) {
assert_se(copy_file_fd(in_fn, out_fd, COPY_REFLINK) >= 0);
assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
- assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
+ assert_se(read(out_fd, buf, sizeof buf) == (ssize_t) strlen(text));
assert_se(streq(buf, text));
unlink(in_fn);
@@ -92,7 +92,7 @@ static void test_copy_tree(void) {
STRV_FOREACH(p, files) {
_cleanup_free_ char *f;
- assert_se(f = strappend(original_dir, *p));
+ assert_se(f = path_join(original_dir, *p));
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
@@ -101,8 +101,8 @@ static void test_copy_tree(void) {
STRV_FOREACH_PAIR(link, p, links) {
_cleanup_free_ char *f, *l;
- assert_se(f = strappend(original_dir, *p));
- assert_se(l = strappend(original_dir, *link));
+ assert_se(f = path_join(original_dir, *p));
+ assert_se(l = path_join(original_dir, *link));
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
@@ -117,7 +117,7 @@ static void test_copy_tree(void) {
_cleanup_free_ char *buf, *f;
size_t sz;
- assert_se(f = strappend(copy_dir, *p));
+ assert_se(f = path_join(copy_dir, *p));
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
index c9272459b4..e1dd2eb32b 100644
--- a/src/test/test-cpu-set-util.c
+++ b/src/test/test-cpu-set-util.c
@@ -2,125 +2,289 @@
#include "alloc-util.h"
#include "cpu-set-util.h"
+#include "string-util.h"
#include "macro.h"
static void test_parse_cpu_set(void) {
- cpu_set_t *c = NULL;
- int ncpus;
+ CPUSet c = {};
+ _cleanup_free_ char *str = NULL;
int cpu;
+ log_info("/* %s */", __func__);
+
+ /* Single value */
+ assert_se(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.set);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_ISSET_S(0, c.allocated, c.set));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 1);
+
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0"));
+ str = mfree(str);
+ cpu_set_reset(&c);
+
/* Simple range (from CPUAffinity example) */
- ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
- c = cpu_set_mfree(c);
+ assert_se(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.set);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_ISSET_S(1, c.allocated, c.set));
+ assert_se(CPU_ISSET_S(2, c.allocated, c.set));
+ assert_se(CPU_ISSET_S(4, c.allocated, c.set));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
+
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "1-2 4"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* A more interesting range */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ assert_se(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0-3 8-11"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Quoted strings */
- ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
+ assert_se(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 4);
for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "8-11"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Use commas as separators */
- ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ assert_se(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Commas with spaces (and trailing comma, space) */
- ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 9);
for (cpu = 0; cpu < 8; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+
+ assert_se(CPU_ISSET_S(63, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0-7 63"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Ranges */
- ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ assert_se(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Ranges with trailing comma, space */
- ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0-3 8-11"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Negative range (returns empty cpu_set) */
- ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
- c = cpu_set_mfree(c);
+ assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 0);
+ cpu_set_reset(&c);
/* Overlapping ranges */
- ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ assert_se(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 12);
for (cpu = 0; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0-11"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Mix ranges and individual CPUs */
- ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
- assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
+ assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 10);
+ assert_se(CPU_ISSET_S(0, c.allocated, c.set));
+ assert_se(CPU_ISSET_S(2, c.allocated, c.set));
for (cpu = 4; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = cpu_set_mfree(c);
+ assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "0 2 4-11"));
+ str = mfree(str);
+ cpu_set_reset(&c);
/* Garbage */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
+ assert_se(parse_cpu_set_full("0 1 2 3 garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
+ assert_se(!c.set);
+ assert_se(c.allocated == 0);
/* Range with garbage */
- ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
+ assert_se(parse_cpu_set_full("0-3 8-garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
+ assert_se(!c.set);
+ assert_se(c.allocated == 0);
/* Empty string */
- c = NULL;
- ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus == 0); /* empty string returns 0 */
- assert_se(!c);
+ assert_se(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(!c.set); /* empty string returns NULL */
+ assert_se(c.allocated == 0);
/* Runaway quoted string */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
+ assert_se(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
+ assert_se(!c.set);
+ assert_se(c.allocated == 0);
+
+ /* Maximum allocation */
+ assert_se(parse_cpu_set_full("8000-8191", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 192);
+ assert_se(str = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", str);
+ str = mfree(str);
+ assert_se(str = cpu_set_to_range_string(&c));
+ log_info("cpu_set_to_range_string: %s", str);
+ assert_se(streq(str, "8000-8191"));
+ str = mfree(str);
+ cpu_set_reset(&c);
+}
+
+static void test_parse_cpu_set_extend(void) {
+ CPUSet c = {};
+ _cleanup_free_ char *s1 = NULL, *s2 = NULL;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 2);
+ assert_se(s1 = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", s1);
+
+ assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
+ assert_se(s2 = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", s2);
+
+ assert_se(parse_cpu_set_extend("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(!c.set);
+ assert_se(c.allocated == 0);
+ log_info("cpu_set_to_string: (null)");
+}
+
+static void test_cpu_set_to_from_dbus(void) {
+ _cleanup_(cpu_set_reset) CPUSet c = {}, c2 = {};
+ _cleanup_free_ char *s = NULL;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(s = cpu_set_to_string(&c));
+ log_info("cpu_set_to_string: %s", s);
+ assert_se(CPU_COUNT_S(c.allocated, c.set) == 104);
+
+ _cleanup_free_ uint8_t *array = NULL;
+ size_t allocated;
+ static const char expected[32] =
+ "\x0A\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\x01";
+
+ assert_se(cpu_set_to_dbus(&c, &array, &allocated) == 0);
+ assert_se(array);
+ assert_se(allocated == c.allocated);
+
+ assert_se(allocated <= sizeof expected);
+ assert_se(allocated >= DIV_ROUND_UP(201u, 8u)); /* We need at least 201 bits for our mask */
+ assert(memcmp(array, expected, allocated) == 0);
+
+ assert_se(cpu_set_from_dbus(array, allocated, &c2) == 0);
+ assert_se(c2.set);
+ assert_se(c2.allocated == c.allocated);
+ assert_se(memcmp(c.set, c2.set, c.allocated) == 0);
+}
+
+static void test_cpus_in_affinity_mask(void) {
+ int r;
+
+ r = cpus_in_affinity_mask();
+ assert(r > 0);
+ log_info("cpus_in_affinity_mask: %d", r);
}
int main(int argc, char *argv[]) {
+ log_info("CPU_ALLOC_SIZE(1) = %zu", CPU_ALLOC_SIZE(1));
+ log_info("CPU_ALLOC_SIZE(9) = %zu", CPU_ALLOC_SIZE(9));
+ log_info("CPU_ALLOC_SIZE(64) = %zu", CPU_ALLOC_SIZE(64));
+ log_info("CPU_ALLOC_SIZE(65) = %zu", CPU_ALLOC_SIZE(65));
+ log_info("CPU_ALLOC_SIZE(1024) = %zu", CPU_ALLOC_SIZE(1024));
+ log_info("CPU_ALLOC_SIZE(1025) = %zu", CPU_ALLOC_SIZE(1025));
+ log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191));
+
test_parse_cpu_set();
+ test_parse_cpu_set_extend();
+ test_cpus_in_affinity_mask();
+ test_cpu_set_to_from_dbus();
return 0;
}
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index 701594fe53..633cc42534 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -7,14 +7,17 @@
#include "bus-util.h"
#include "manager.h"
#include "rm-rf.h"
+#include "strv.h"
#include "test-helper.h"
#include "tests.h"
+#include "service.h"
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
_cleanup_(manager_freep) Manager *m = NULL;
- Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL, *unit_with_multiple_dashes = NULL;
+ Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL,
+ *h = NULL, *i = NULL, *a_conj = NULL, *unit_with_multiple_dashes = NULL;
Job *j;
int r;
@@ -94,6 +97,30 @@ int main(int argc, char *argv[]) {
assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
+ printf("Load5:\n");
+ manager_clear_jobs(m);
+ assert_se(manager_load_startable_unit_or_warn(m, "i.service", NULL, &i) >= 0);
+ SERVICE(a)->state = SERVICE_RUNNING;
+ SERVICE(d)->state = SERVICE_RUNNING;
+ manager_dump_units(m, stdout, "\t");
+
+ printf("Test11: (Start/stop job ordering, execution cycle)\n");
+ assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, NULL, &j) == 0);
+ assert_se(a->job && a->job->type == JOB_STOP);
+ assert_se(d->job && d->job->type == JOB_STOP);
+ assert_se(b->job && b->job->type == JOB_START);
+ manager_dump_jobs(m, stdout, "\t");
+
+ printf("Load6:\n");
+ manager_clear_jobs(m);
+ assert_se(manager_load_startable_unit_or_warn(m, "a-conj.service", NULL, &a_conj) >= 0);
+ SERVICE(a)->state = SERVICE_DEAD;
+ manager_dump_units(m, stdout, "\t");
+
+ printf("Test12: (Trivial cycle, Unfixable)\n");
+ assert_se(manager_add_job(m, JOB_START, a_conj, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
+ manager_dump_jobs(m, stdout, "\t");
+
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
diff --git a/src/test/test-env-file.c b/src/test/test-env-file.c
new file mode 100644
index 0000000000..47f86a5676
--- /dev/null
+++ b/src/test/test-env-file.c
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "env-file.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "strv.h"
+#include "tests.h"
+#include "tmpfile-util.h"
+
+#define env_file_1 \
+ "a=a\n" \
+ "b=b\\\n" \
+ "c\n" \
+ "d=d\\\n" \
+ "e\\\n" \
+ "f\n" \
+ "g=g\\ \n" \
+ "h=h\n" \
+ "i=i\\"
+
+#define env_file_2 \
+ "a=a\\\n"
+
+#define env_file_3 \
+ "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
+ "#--nouser-config \\\n" \
+ "normal=line"
+
+#define env_file_4 \
+ "# Generated\n" \
+ "\n" \
+ "HWMON_MODULES=\"coretemp f71882fg\"\n" \
+ "\n" \
+ "# For compatibility reasons\n" \
+ "\n" \
+ "MODULE_0=coretemp\n" \
+ "MODULE_1=f71882fg"
+
+#define env_file_5 \
+ "a=\n" \
+ "b="
+
+static void test_load_env_file_1(void) {
+ _cleanup_strv_free_ char **data = NULL;
+ int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_close_ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1));
+
+ 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"));
+ assert_se(streq(data[2], "d=def"));
+ assert_se(streq(data[3], "g=g "));
+ assert_se(streq(data[4], "h=h"));
+ assert_se(streq(data[5], "i=i"));
+ assert_se(data[6] == NULL);
+}
+
+static void test_load_env_file_2(void) {
+ _cleanup_strv_free_ char **data = NULL;
+ int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_close_ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2));
+
+ r = load_env_file(NULL, name, &data);
+ assert_se(r == 0);
+ assert_se(streq(data[0], "a=a"));
+ assert_se(data[1] == NULL);
+}
+
+static void test_load_env_file_3(void) {
+ _cleanup_strv_free_ char **data = NULL;
+ int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_close_ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3));
+
+ r = load_env_file(NULL, name, &data);
+ assert_se(r == 0);
+ assert_se(data == NULL);
+}
+
+static void test_load_env_file_4(void) {
+ _cleanup_strv_free_ char **data = NULL;
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_close_ int fd;
+ int r;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4));
+
+ 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"));
+ assert_se(streq(data[2], "MODULE_1=f71882fg"));
+ assert_se(data[3] == NULL);
+}
+
+static void test_load_env_file_5(void) {
+ _cleanup_strv_free_ char **data = NULL;
+ int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_close_ int fd;
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5));
+
+ r = load_env_file(NULL, name, &data);
+ assert_se(r == 0);
+ assert_se(streq(data[0], "a="));
+ assert_se(streq(data[1], "b="));
+ assert_se(data[2] == NULL);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ test_load_env_file_1();
+ test_load_env_file_2();
+ test_load_env_file_3();
+ test_load_env_file_4();
+ test_load_env_file_5();
+}
diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c
index f57a26021c..17dacda70f 100644
--- a/src/test/test-env-util.c
+++ b/src/test/test-env-util.c
@@ -122,10 +122,10 @@ static void test_env_strv_get_n(void) {
assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
assert_se(!strv_env_get_n(env, "PATH", 4, 0));
- assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
- getenv("PATH")));
- assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
- getenv("PATH")));
+ assert_se(streq_ptr(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
+ getenv("PATH")));
+ assert_se(streq_ptr(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
+ getenv("PATH")));
}
static void test_replace_env(bool braceless) {
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
index 4ee4aa974d..add17f9547 100644
--- a/src/test/test-escape.c
+++ b/src/test/test-escape.c
@@ -6,10 +6,45 @@
#include "tests.h"
static void test_cescape(void) {
- _cleanup_free_ char *escaped;
+ _cleanup_free_ char *t;
- assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
- assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+ assert_se(t = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+ assert_se(streq(t, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_xescape(void) {
+ _cleanup_free_ char *t;
+
+ assert_se(t = xescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", ""));
+ assert_se(streq(t, "abc\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb"));
+}
+
+static void test_xescape_full(bool eight_bits) {
+ const char* escaped = !eight_bits ?
+ "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb" :
+ "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\177\234\313";
+ const unsigned full_fit = !eight_bits ? 55 : 46;
+
+ for (unsigned i = 0; i < 60; i++) {
+ _cleanup_free_ char *t;
+
+ assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, eight_bits));
+
+ log_info("%02d: %s", i, t);
+
+ if (i >= full_fit)
+ assert_se(streq(t, escaped));
+ else if (i >= 3) {
+ /* We need up to four columns, so up to three three columns may be wasted */
+ assert_se(strlen(t) == i || strlen(t) == i - 1 || strlen(t) == i - 2 || strlen(t) == i - 3);
+ assert_se(strneq(t, escaped, i - 3) || strneq(t, escaped, i - 4) ||
+ strneq(t, escaped, i - 5) || strneq(t, escaped, i - 6));
+ assert_se(endswith(t, "..."));
+ } else {
+ assert_se(strlen(t) == i);
+ assert_se(strneq(t, "...", i));
+ }
+ }
}
static void test_cunescape(void) {
@@ -123,6 +158,9 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_cescape();
+ test_xescape();
+ test_xescape_full(false);
+ test_xescape_full(true);
test_cunescape();
test_shell_escape();
test_shell_maybe_quote();
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
index 25ca7a2bc9..ec51891634 100644
--- a/src/test/test-exec-util.c
+++ b/src/test/test-exec-util.c
@@ -324,7 +324,7 @@ static void test_environment_gathering(void) {
assert_se(chmod(name3, 0755) == 0);
/* 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
+ * any PATH in the environment 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 */
@@ -361,7 +361,10 @@ static void test_environment_gathering(void) {
assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file"));
/* reset environ PATH */
- (void) setenv("PATH", old, 1);
+ if (old)
+ (void) setenv("PATH", old, 1);
+ else
+ (void) unsetenv("PATH");
}
static void test_error_catching(void) {
@@ -399,6 +402,50 @@ static void test_error_catching(void) {
assert_se(r == 42);
}
+static void test_exec_command_flags_from_strv(void) {
+ ExecCommandFlags flags = 0;
+ char **valid_strv = STRV_MAKE("no-env-expand", "no-setuid", "ignore-failure");
+ char **invalid_strv = STRV_MAKE("no-env-expand", "no-setuid", "nonexistent-option", "ignore-failure");
+ int r;
+
+ r = exec_command_flags_from_strv(valid_strv, &flags);
+
+ assert_se(r == 0);
+ assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND));
+ assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID));
+ assert_se(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE));
+ assert_se(!FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC));
+ assert_se(!FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED));
+
+ r = exec_command_flags_from_strv(invalid_strv, &flags);
+
+ assert_se(r == -EINVAL);
+}
+
+static void test_exec_command_flags_to_strv(void) {
+ _cleanup_strv_free_ char **opts = NULL, **empty_opts = NULL, **invalid_opts = NULL;
+ ExecCommandFlags flags = 0;
+ int r;
+
+ flags |= (EXEC_COMMAND_AMBIENT_MAGIC|EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_IGNORE_FAILURE);
+
+ r = exec_command_flags_to_strv(flags, &opts);
+
+ assert_se(r == 0);
+ assert_se(strv_equal(opts, STRV_MAKE("ignore-failure", "ambient", "no-env-expand")));
+
+ r = exec_command_flags_to_strv(0, &empty_opts);
+
+ assert_se(r == 0);
+ assert_se(strv_equal(empty_opts, STRV_MAKE_EMPTY));
+
+ flags = _EXEC_COMMAND_FLAGS_INVALID;
+
+ r = exec_command_flags_to_strv(flags, &invalid_opts);
+
+ assert_se(r == -EINVAL);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@@ -408,6 +455,8 @@ int main(int argc, char *argv[]) {
test_stdout_gathering();
test_environment_gathering();
test_error_catching();
+ test_exec_command_flags_from_strv();
+ test_exec_command_flags_to_strv();
return 0;
}
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 9f1cb0ca38..435ab39cd2 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -33,7 +33,13 @@ static bool can_unshare;
typedef void (*test_function_t)(Manager *m);
-static void check(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
+static int cld_dumped_to_killed(int code) {
+ /* Depending on the system, seccomp version, … some signals might result in dumping, others in plain
+ * killing. Let's ignore the difference here, and map both cases to CLD_KILLED */
+ return code == CLD_DUMPED ? CLD_KILLED : code;
+}
+
+static void wait_for_service_finish(Manager *m, Unit *unit) {
Service *service = NULL;
usec_t ts;
usec_t timeout = 2 * USEC_PER_MINUTE;
@@ -61,17 +67,49 @@ static void check(const char *func, Manager *m, Unit *unit, int status_expected,
exit(EXIT_FAILURE);
}
}
+}
+
+static void check_main_result(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
+ Service *service = NULL;
+
+ assert_se(m);
+ assert_se(unit);
+
+ wait_for_service_finish(m, unit);
+
+ service = SERVICE(unit);
exec_status_dump(&service->main_exec_status, stdout, "\t");
+
+ if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) {
+ log_error("%s: %s: exit code %d, expected %d",
+ func, unit->id,
+ service->main_exec_status.code, code_expected);
+ abort();
+ }
+
if (service->main_exec_status.status != status_expected) {
log_error("%s: %s: exit status %d, expected %d",
func, unit->id,
service->main_exec_status.status, status_expected);
abort();
}
- if (service->main_exec_status.code != code_expected) {
- log_error("%s: %s: exit code %d, expected %d",
+}
+
+static void check_service_result(const char *func, Manager *m, Unit *unit, ServiceResult result_expected) {
+ Service *service = NULL;
+
+ assert_se(m);
+ assert_se(unit);
+
+ wait_for_service_finish(m, unit);
+
+ service = SERVICE(unit);
+
+ if (service->result != result_expected) {
+ log_error("%s: %s: service end result %s, expected %s",
func, unit->id,
- service->main_exec_status.code, code_expected);
+ service_result_to_string(service->result),
+ service_result_to_string(result_expected));
abort();
}
}
@@ -165,7 +203,17 @@ static void test(const char *func, Manager *m, const char *unit_name, int status
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
assert_se(unit_start(unit) >= 0);
- check(func, m, unit, status_expected, code_expected);
+ check_main_result(func, m, unit, status_expected, code_expected);
+}
+
+static void test_service(const char *func, Manager *m, const char *unit_name, ServiceResult result_expected) {
+ Unit *unit;
+
+ assert_se(unit_name);
+
+ assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
+ assert_se(unit_start(unit) >= 0);
+ check_service_result(func, m, unit, result_expected);
}
static void test_exec_bindpaths(Manager *m) {
@@ -179,13 +227,12 @@ static void test_exec_bindpaths(Manager *m) {
}
static void test_exec_cpuaffinity(Manager *m) {
- _cleanup_cpu_free_ cpu_set_t *c = NULL;
- unsigned n;
+ _cleanup_(cpu_set_reset) CPUSet c = {};
- assert_se(c = cpu_set_malloc(&n));
- assert_se(sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0);
+ assert_se(cpu_set_realloc(&c, 8192) >= 0); /* just allocate the maximum possible size */
+ assert_se(sched_getaffinity(0, c.allocated, c.set) >= 0);
- if (CPU_ISSET_S(0, CPU_ALLOC_SIZE(n), c) == 0) {
+ if (!CPU_ISSET_S(0, c.allocated, c.set)) {
log_notice("Cannot use CPU 0, skipping %s", __func__);
return;
}
@@ -193,8 +240,8 @@ static void test_exec_cpuaffinity(Manager *m) {
test(__func__, m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
test(__func__, m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
- if (CPU_ISSET_S(1, CPU_ALLOC_SIZE(n), c) == 0 ||
- CPU_ISSET_S(2, CPU_ALLOC_SIZE(n), c) == 0) {
+ if (!CPU_ISSET_S(1, c.allocated, c.set) ||
+ !CPU_ISSET_S(2, c.allocated, c.set)) {
log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__);
return;
}
@@ -424,7 +471,12 @@ static void test_exec_restrictnamespaces(Manager *m) {
}
static void test_exec_systemcallfilter_system(Manager *m) {
-#if HAVE_SECCOMP
+/* Skip this particular test case when running under ASan, as
+ * LSan intermittently segfaults when accessing memory right
+ * after the test finishes. Generally, ASan & LSan don't like
+ * the seccomp stuff.
+ */
+#if HAVE_SECCOMP && !HAS_FEATURE_ADDRESS_SANITIZER
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
@@ -711,6 +763,11 @@ static void test_exec_standardoutput_append(Manager *m) {
test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED);
}
+static void test_exec_condition(Manager *m) {
+ test_service(__func__, m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
+ test_service(__func__, m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
+}
+
typedef struct test_entry {
test_function_t f;
const char *name;
@@ -740,7 +797,6 @@ static int run_tests(UnitFileScope scope, const test_entry tests[], char **patte
return 0;
}
-
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_free_ char *test_execute_path = NULL;
@@ -750,6 +806,7 @@ int main(int argc, char *argv[]) {
entry(test_exec_ambientcapabilities),
entry(test_exec_bindpaths),
entry(test_exec_capabilityboundingset),
+ entry(test_exec_condition),
entry(test_exec_cpuaffinity),
entry(test_exec_environment),
entry(test_exec_environmentfile),
diff --git a/src/test/test-exit-status.c b/src/test/test-exit-status.c
new file mode 100644
index 0000000000..a007bda5c4
--- /dev/null
+++ b/src/test/test-exit-status.c
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "exit-status.h"
+#include "string-util.h"
+#include "tests.h"
+
+static void test_exit_status_to_string(void) {
+ log_info("/* %s */", __func__);
+
+ for (int i = -1; i <= 256; i++) {
+ const char *s, *class;
+
+ s = exit_status_to_string(i, EXIT_STATUS_FULL);
+ class = exit_status_class(i);
+ log_info("%d: %s%s%s%s",
+ i, s ?: "-",
+ class ? " (" : "", class ?: "", class ? ")" : "");
+
+ if (s)
+ assert_se(exit_status_from_string(s) == i);
+ }
+}
+
+static void test_exit_status_from_string(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(exit_status_from_string("11") == 11);
+ assert_se(exit_status_from_string("-1") == -ERANGE);
+ assert_se(exit_status_from_string("256") == -ERANGE);
+ assert_se(exit_status_from_string("foo") == -EINVAL);
+ assert_se(exit_status_from_string("SUCCESS") == 0);
+ assert_se(exit_status_from_string("FAILURE") == 1);
+}
+
+static void test_exit_status_NUMA_POLICY(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_FULL), "NUMA_POLICY"));
+ assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_SYSTEMD), "NUMA_POLICY"));
+ assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_BSD));
+ assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_LSB));
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_exit_status_to_string();
+ test_exit_status_from_string();
+ test_exit_status_NUMA_POLICY();
+
+ return 0;
+}
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
index 30019382ae..bf47a598a9 100644
--- a/src/test/test-extract-word.c
+++ b/src/test/test-extract-word.c
@@ -43,12 +43,12 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "\"foobar\" \'waldo\'";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "foobar"));
free(t);
assert_se(p == original + 9);
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "waldo"));
free(t);
assert_se(isempty(p));
@@ -64,7 +64,7 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "\"";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL);
assert_se(p == original + 1);
p = original = "\'";
@@ -74,7 +74,7 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "\'";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL);
assert_se(p == original + 1);
p = original = "\'fooo";
@@ -83,18 +83,42 @@ static void test_extract_first_word(void) {
free(t);
assert_se(isempty(p));
+ p = original = "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1);
+ assert_se(streq(t, "KEY=val"));
+ free(t);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1);
+ assert_se(streq(t, "KEY2=val with space"));
+ free(t);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1);
+ assert_se(streq(t, "KEY3=val with \"quotation\""));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "KEY=val \"KEY2=val space\" \"KEY3=val with \\\"quotation\\\"\"";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1);
+ assert_se(streq(t, "KEY=val"));
+ free(t);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1);
+ assert_se(streq(t, "\"KEY2=val"));
+ free(t);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1);
+ assert_se(streq(t, "space\""));
+ free(t);
+ assert_se(startswith(p, "\"KEY3="));
+
p = original = "\'fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL);
assert_se(p == original + 5);
p = original = "\'fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0);
assert_se(streq(t, "fooo"));
free(t);
assert_se(isempty(p));
p = original = "\"fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0);
assert_se(streq(t, "fooo"));
free(t);
assert_se(isempty(p));
@@ -106,7 +130,7 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "yay\'foo\'bar";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "yayfoobar"));
free(t);
assert_se(isempty(p));
@@ -135,7 +159,7 @@ static void test_extract_first_word(void) {
free(t);
assert_se(p == original + 13);
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE) > 0);
assert_se(streq(t, "pi\360\237\222\251le"));
free(t);
assert_se(isempty(p));
@@ -169,7 +193,7 @@ static void test_extract_first_word(void) {
assert_se(p == original + 5);
p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0);
assert_se(streq(t, "foo"));
free(t);
assert_se(isempty(p));
@@ -205,17 +229,17 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
assert_se(p == original + 5);
p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "foo\\"));
free(t);
assert_se(isempty(p));
p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "foo\\"));
free(t);
assert_se(isempty(p));
@@ -265,12 +289,12 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "-N ''";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "-N"));
free(t);
assert_se(p == original + 3);
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, ""));
free(t);
assert_se(isempty(p));
@@ -340,12 +364,12 @@ static void test_extract_first_word_and_warn(void) {
assert_se(isempty(p));
p = original = "\"foobar\" \'waldo\'";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "foobar"));
free(t);
assert_se(p == original + 9);
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "waldo"));
free(t);
assert_se(isempty(p));
@@ -355,19 +379,19 @@ static void test_extract_first_word_and_warn(void) {
assert_se(isempty(p));
p = original = "\"";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL);
assert_se(p == original + 1);
p = original = "\'";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL);
assert_se(p == original + 1);
p = original = "\'fooo";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL);
assert_se(p == original + 5);
p = original = "\'fooo";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "fooo"));
free(t);
assert_se(isempty(p));
@@ -390,7 +414,7 @@ static void test_extract_first_word_and_warn(void) {
free(t);
assert_se(p == original + 13);
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "pi\360\237\222\251le"));
free(t);
assert_se(isempty(p));
@@ -414,21 +438,21 @@ static void test_extract_first_word_and_warn(void) {
assert_se(isempty(p));
p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL);
assert_se(p == original + 5);
p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "foo"));
free(t);
assert_se(isempty(p));
p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
assert_se(p == original + 5);
p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "foo"));
free(t);
assert_se(isempty(p));
@@ -488,7 +512,7 @@ static void test_extract_many_words(void) {
free(b);
p = original = "'foobar' wa\"ld\"i ";
- assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2);
+ assert_se(extract_many_words(&p, NULL, EXTRACT_UNQUOTE, &a, &b, &c, NULL) == 2);
assert_se(isempty(p));
assert_se(streq_ptr(a, "foobar"));
assert_se(streq_ptr(b, "waldi"));
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 2ff5b9a69d..56af5a8bc3 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -427,7 +427,7 @@ static void test_write_string_file(void) {
static void test_write_string_file_no_create(void) {
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
_cleanup_close_ int fd;
- char buf[64] = {0};
+ char buf[64] = {};
fd = mkostemp_safe(fn);
assert_se(fd >= 0);
@@ -435,7 +435,7 @@ static void test_write_string_file_no_create(void) {
assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
assert_se(write_string_file(fn, "boohoo", 0) == 0);
- assert_se(read(fd, buf, sizeof(buf)) == STRLEN("boohoo\n"));
+ assert_se(read(fd, buf, sizeof buf) == (ssize_t) strlen("boohoo\n"));
assert_se(streq(buf, "boohoo\n"));
}
@@ -629,7 +629,6 @@ static void test_tempfn(void) {
static const char chars[] =
"Aąę„”\n루\377";
-
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
@@ -637,7 +636,7 @@ static void test_fgetc(void) {
_cleanup_fclose_ FILE *f = NULL;
char c;
- f = fmemopen((void*) chars, sizeof(chars), "re");
+ f = fmemopen_unlocked((void*) chars, sizeof(chars), "re");
assert_se(f);
for (unsigned i = 0; i < sizeof(chars); i++) {
@@ -717,7 +716,7 @@ static void test_read_line_one_file(FILE *f) {
line = mfree(line);
/* 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. */
+ * character after the previous limit. Let's make use of that to continue our test. */
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);
@@ -727,7 +726,7 @@ static void test_read_line_one_file(FILE *f) {
static void test_read_line(void) {
_cleanup_fclose_ FILE *f = NULL;
- f = fmemopen((void*) buffer, sizeof(buffer), "re");
+ f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re");
assert_se(f);
test_read_line_one_file(f);
@@ -792,7 +791,7 @@ static void test_read_line4(void) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *s = NULL;
- assert_se(f = fmemopen((void*) eof_endings[i].string, eof_endings[i].length, "r"));
+ assert_se(f = fmemopen_unlocked((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);
@@ -813,7 +812,7 @@ static void test_read_nul_string(void) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *s = NULL;
- assert_se(f = fmemopen((void*) test, sizeof(test)-1, "r"));
+ assert_se(f = fmemopen_unlocked((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);
diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c
index 5bede5c75b..def9cbda2f 100644
--- a/src/test/test-format-table.c
+++ b/src/test/test-format-table.c
@@ -34,6 +34,7 @@ int main(int argc, char *argv[]) {
_cleanup_(table_unrefp) Table *t = NULL;
_cleanup_free_ char *formatted = NULL;
+ assert_se(setenv("SYSTEMD_COLORS", "0", 1) >= 0);
assert_se(setenv("COLUMNS", "40", 1) >= 0);
assert_se(t = table_new("one", "two", "three"));
@@ -48,6 +49,7 @@ int main(int argc, char *argv[]) {
assert_se(table_add_many(t,
TABLE_STRING, "a long field",
TABLE_STRING, "yyy",
+ TABLE_SET_UPPERCASE, 1,
TABLE_BOOLEAN, false) >= 0);
assert_se(table_format(t, &formatted) >= 0);
@@ -56,7 +58,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(formatted,
"ONE TWO THREE\n"
"xxx yyy yes\n"
- "a long field yyy no\n"));
+ "a long field YYY no\n"));
formatted = mfree(formatted);
@@ -68,7 +70,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(formatted,
"ONE TWO THREE\n"
"xxx yyy yes\n"
- "a long field yyy no\n"));
+ "a long field YYY no\n"));
formatted = mfree(formatted);
@@ -79,7 +81,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(formatted,
"ONE TWO THR…\n"
"xxx yyy yes\n"
- "a … yyy no\n"));
+ "a … YYY no\n"));
formatted = mfree(formatted);
@@ -113,7 +115,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(formatted,
"ONE TWO THREE\n"
- "a long field yyy no\n"
+ "a long field YYY no\n"
"xxx yyy yes\n"));
formatted = mfree(formatted);
@@ -139,7 +141,7 @@ int main(int argc, char *argv[]) {
printf("%s\n", formatted);
assert_se(streq(formatted,
- "a long field yyy no\n"
+ "a long field YYY no\n"
"fäää zzz no\n"
"fäää uuu yes\n"
"xxx yyy yes\n"
diff --git a/src/test/test-format-util.c b/src/test/test-format-util.c
new file mode 100644
index 0000000000..6558ee2b0a
--- /dev/null
+++ b/src/test/test-format-util.c
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "format-util.h"
+#include "macro.h"
+#include "string-util.h"
+
+static void test_format_bytes_one(uint64_t val, bool trailing_B, const char *iec_with_p, const char *iec_without_p,
+ const char *si_with_p, const char *si_without_p) {
+ char buf[FORMAT_BYTES_MAX];
+
+ assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_with_p));
+ assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_without_p));
+ assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), si_with_p));
+ assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, trailing_B ? FORMAT_BYTES_TRAILING_B : 0), si_without_p));
+}
+
+static void test_format_bytes(void) {
+ test_format_bytes_one(900, true, "900B", "900B", "900B", "900B");
+ test_format_bytes_one(900, false, "900", "900", "900", "900");
+ test_format_bytes_one(1023, true, "1023B", "1023B", "1.0K", "1K");
+ test_format_bytes_one(1023, false, "1023", "1023", "1.0K", "1K");
+ test_format_bytes_one(1024, true, "1.0K", "1K", "1.0K", "1K");
+ test_format_bytes_one(1024, false, "1.0K", "1K", "1.0K", "1K");
+ test_format_bytes_one(1100, true, "1.0K", "1K", "1.1K", "1K");
+ test_format_bytes_one(1500, true, "1.4K", "1K", "1.5K", "1K");
+ test_format_bytes_one(UINT64_C(3)*1024*1024, true, "3.0M", "3M", "3.1M", "3M");
+ test_format_bytes_one(UINT64_C(3)*1024*1024*1024, true, "3.0G", "3G", "3.2G", "3G");
+ test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024, true, "3.0T", "3T", "3.2T", "3T");
+ test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024, true, "3.0P", "3P", "3.3P", "3P");
+ test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024*1024, true, "3.0E", "3E", "3.4E", "3E");
+ test_format_bytes_one(UINT64_MAX, true, NULL, NULL, NULL, NULL);
+ test_format_bytes_one(UINT64_MAX, false, NULL, NULL, NULL, NULL);
+}
+
+int main(void) {
+ test_format_bytes();
+
+ return 0;
+}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index f0f015056e..7cf4f4976b 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -15,6 +15,7 @@
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
+#include "umask-util.h"
#include "user-util.h"
#include "util.h"
#include "virt.h"
@@ -635,7 +636,6 @@ static void test_touch_file(void) {
assert_se(st.st_uid == test_uid);
assert_se(st.st_gid == test_gid);
assert_se(S_ISLNK(st.st_mode));
- assert_se((st.st_mode & 0777) == 0640);
assert_se(timespec_load(&st.st_mtim) == test_mtime);
}
@@ -746,22 +746,67 @@ static void test_rename_noreplace(void) {
}
}
+static void test_chmod_and_chown(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *d = NULL;
+ _unused_ _cleanup_umask_ mode_t u = umask(0000);
+ struct stat st;
+ const char *p;
+
+ if (geteuid() != 0)
+ return;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(mkdtemp_malloc(NULL, &d) >= 0);
+
+ p = strjoina(d, "/reg");
+ assert_se(mknod(p, S_IFREG | 0123, 0) >= 0);
+
+ assert_se(chmod_and_chown(p, S_IFREG | 0321, 1, 2) >= 0);
+ assert_se(chmod_and_chown(p, S_IFDIR | 0555, 3, 4) == -EINVAL);
+
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0321);
+
+ p = strjoina(d, "/dir");
+ assert_se(mkdir(p, 0123) >= 0);
+
+ assert_se(chmod_and_chown(p, S_IFDIR | 0321, 1, 2) >= 0);
+ assert_se(chmod_and_chown(p, S_IFREG | 0555, 3, 4) == -EINVAL);
+
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 07777) == 0321);
+
+ p = strjoina(d, "/lnk");
+ assert_se(symlink("idontexist", p) >= 0);
+
+ assert_se(chmod_and_chown(p, S_IFLNK | 0321, 1, 2) >= 0);
+ assert_se(chmod_and_chown(p, S_IFREG | 0555, 3, 4) == -EINVAL);
+ assert_se(chmod_and_chown(p, S_IFDIR | 0555, 3, 4) == -EINVAL);
+
+ assert_se(lstat(p, &st) >= 0);
+ assert_se(S_ISLNK(st.st_mode));
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
arg_test_dir = argv[1];
+ test_chase_symlinks();
test_unlink_noerrno();
- test_get_files_in_directory();
test_readlink_and_make_absolute();
+ test_get_files_in_directory();
test_var_tmp();
- test_chase_symlinks();
test_dot_or_dot_dot();
test_access_fd();
test_touch_file();
test_unlinkat_deallocate();
test_fsync_directory_of_file();
test_rename_noreplace();
+ test_chmod_and_chown();
return 0;
}
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index fdb0c7e87f..57cf89ff53 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -831,6 +831,31 @@ static void test_hashmap_free(void) {
}
}
+typedef struct Item {
+ int seen;
+} Item;
+static void item_seen(Item *item) {
+ item->seen++;
+}
+
+static void test_hashmap_free_with_destructor(void) {
+ Hashmap *m;
+ 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);
+
+ m = hashmap_free_with_destructor(m, item_seen);
+ 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_hashmap_first(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
@@ -978,9 +1003,65 @@ static void test_hashmap_reserve(void) {
assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM);
}
+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);
+ assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0);
+ assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST);
+ assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0);
+ assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST);
+ assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0);
+ assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST);
+
+ assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4));
+ assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4));
+ assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4));
+ assert_se(!hashmap_get(h, "foox"));
+ assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6));
+ assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6));
+ assert_se(!hashmap_get(h, "/foo////bar////quux/////"));
+}
+
+static void test_string_strv_hashmap(void) {
+ _cleanup_hashmap_free_ Hashmap *m = NULL;
+ char **s;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 1);
+ assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
+ assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 1);
+ assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 0);
+ assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
+ assert_se(hashmap_contains(m, "foo"));
+
+ s = hashmap_get(m, "foo");
+ assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
+
+ assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 1);
+ assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
+ assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 1);
+ assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 0);
+ assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
+ assert_se(hashmap_contains(m, "xxx"));
+
+ s = hashmap_get(m, "xxx");
+ assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
+}
+
void test_hashmap_funcs(void) {
- log_parse_environment();
- log_open();
+ log_info("/************ %s ************/", __func__);
test_hashmap_copy();
test_hashmap_get_strv();
@@ -1005,6 +1086,7 @@ void test_hashmap_funcs(void) {
test_hashmap_size();
test_hashmap_many();
test_hashmap_free();
+ test_hashmap_free_with_destructor();
test_hashmap_first();
test_hashmap_first_key();
test_hashmap_steal_first_key();
@@ -1012,4 +1094,6 @@ void test_hashmap_funcs(void) {
test_hashmap_clear_free_free();
test_hashmap_clear_free_with_destructor();
test_hashmap_reserve();
+ test_path_hashmap();
+ test_string_strv_hashmap();
}
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index ee4c0e66db..1a6e8ffa58 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -31,31 +31,6 @@ static void test_ordered_hashmap_next(void) {
assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3)));
}
-typedef struct Item {
- int seen;
-} Item;
-static void item_seen(Item *item) {
- item->seen++;
-}
-
-static void test_hashmap_free_with_destructor(void) {
- Hashmap *m;
- 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);
-
- m = hashmap_free_with_destructor(m, item_seen);
- 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_uint64_compare_func(void) {
const uint64_t a = 0x100, b = 0x101;
@@ -134,47 +109,24 @@ static void test_iterated_cache(void) {
assert_se(iterated_cache_free(c) == NULL);
}
-static void test_path_hashmap(void) {
- _cleanup_hashmap_free_ Hashmap *h = NULL;
+int main(int argc, const char *argv[]) {
+ /* This file tests in test-hashmap-plain.c, and tests in test-hashmap-ordered.c, which is generated
+ * from test-hashmap-plain.c. Hashmap tests should be added to test-hashmap-plain.c, and here only if
+ * they don't apply to ordered hashmaps. */
- log_info("/* %s */", __func__);
+ log_parse_environment();
+ log_open();
- assert_se(h = hashmap_new(&path_hash_ops));
-
- assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0);
- assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0);
- assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST);
- assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0);
- assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST);
- assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0);
- assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST);
-
- assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1));
- assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1));
- assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1));
- assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2));
- assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2));
- assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2));
- assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4));
- assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4));
- assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4));
- assert_se(!hashmap_get(h, "foox"));
- assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6));
- assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6));
- assert_se(!hashmap_get(h, "/foo////bar////quux/////"));
-}
-
-int main(int argc, const char *argv[]) {
test_hashmap_funcs();
test_ordered_hashmap_funcs();
+ log_info("/************ non-shared tests ************/");
+
test_ordered_hashmap_next();
- test_hashmap_free_with_destructor();
test_uint64_compare_func();
test_trivial_compare_func();
test_string_compare_func();
test_iterated_cache();
- test_path_hashmap();
return 0;
}
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index 8840788310..eea0765b7a 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -52,7 +52,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(q, UUID_WALDI));
b = mfree(b);
- assert_se(asprintf(&b, ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36);
+ assert_se(asprintf(&b, SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36);
printf("waldi4: %s\n", b);
assert_se(streq(q, b));
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index cfddfe19a7..323e1124ba 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -112,7 +112,7 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
- /* Disabling a disabled unit must suceed but be a NOP */
+ /* Disabling a disabled unit must succeed but be a NOP */
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
assert_se(n_changes == 0);
unit_file_changes_free(changes, n_changes);
diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c
index cddbfa7022..7e898735c9 100644
--- a/src/test/test-journal-importer.c
+++ b/src/test/test-journal-importer.c
@@ -21,7 +21,7 @@ static void assert_iovec_entry(const struct iovec *iovec, const char* content) {
"0::/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service\n"
static void test_basic_parsing(void) {
- _cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ _cleanup_(journal_importer_cleanup) JournalImporter imp = JOURNAL_IMPORTER_INIT(-1);
_cleanup_free_ char *journal_data_path = NULL;
int r;
@@ -52,7 +52,7 @@ static void test_basic_parsing(void) {
}
static void test_bad_input(void) {
- _cleanup_(journal_importer_cleanup) JournalImporter imp = {};
+ _cleanup_(journal_importer_cleanup) JournalImporter imp = JOURNAL_IMPORTER_INIT(-1);
_cleanup_free_ char *journal_data_path = NULL;
int r;
diff --git a/src/test/test-json.c b/src/test/test-json.c
index 9b8a2a9422..a6613043b9 100644
--- a/src/test/test-json.c
+++ b/src/test/test-json.c
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "json-internal.h"
#include "json.h"
#include "string-util.h"
@@ -88,6 +89,7 @@ static void test_variant(const char *data, Test test) {
r = json_variant_format(v, 0, &s);
assert_se(r >= 0);
assert_se(s);
+ assert_se((size_t) r == strlen(s));
log_info("formatted normally: %s\n", s);
@@ -104,6 +106,7 @@ static void test_variant(const char *data, Test test) {
r = json_variant_format(v, JSON_FORMAT_PRETTY, &s);
assert_se(r >= 0);
assert_se(s);
+ assert_se((size_t) r == strlen(s));
log_info("formatted prettily:\n%s", s);
@@ -119,12 +122,14 @@ static void test_variant(const char *data, Test test) {
r = json_variant_format(v, JSON_FORMAT_COLOR, &s);
assert_se(r >= 0);
assert_se(s);
+ assert_se((size_t) r == strlen(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);
+ assert_se((size_t) r == strlen(s));
printf("Pretty with color:\n%s\n", s);
if (test)
@@ -358,7 +363,7 @@ static void test_source(void) {
"%s"
"--- original end ---\n", data);
- assert_se(f = fmemopen((void*) data, strlen(data), "r"));
+ assert_se(f = fmemopen_unlocked((void*) data, strlen(data), "r"));
assert_se(json_parse_file(f, "waldo", &v, NULL, NULL) >= 0);
diff --git a/src/test/test-libmount.c b/src/test/test-libmount.c
index fc28f27d53..c3395493d4 100644
--- a/src/test/test-libmount.c
+++ b/src/test/test-libmount.c
@@ -21,13 +21,10 @@ static void test_libmount_unescaping_one(
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
_cleanup_fclose_ FILE *f = NULL;
- assert_se(table = mnt_new_table());
- assert_se(iter = mnt_new_iter(MNT_ITER_FORWARD));
-
f = fmemopen((char*) string, strlen(string), "re");
assert_se(f);
- assert_se(mnt_table_parse_stream(table, f, title) >= 0);
+ assert_se(libmount_parse(title, f, &table, &iter) >= 0);
struct libmnt_fs *fs;
const char *source, *target;
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index f634ca28db..dcb5bcc254 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -158,7 +158,7 @@ static int enumerate_print_list(struct udev_enumerate *enumerate) {
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
- if (device != NULL) {
+ if (device) {
log_info("device: '%s' (%s)",
udev_device_get_syspath(device),
udev_device_get_subsystem(device));
@@ -249,7 +249,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
udev_enumerate_scan_devices(udev_enumerate);
@@ -258,7 +258,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'net' + duplicated scan + null + zero");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, "net");
udev_enumerate_scan_devices(udev_enumerate);
@@ -278,7 +278,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'block'");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate,"block");
r = udev_enumerate_add_match_is_initialized(udev_enumerate);
@@ -292,7 +292,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'not block'");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block");
udev_enumerate_scan_devices(udev_enumerate);
@@ -301,7 +301,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'pci, mem, vc'");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, "pci");
udev_enumerate_add_match_subsystem(udev_enumerate, "mem");
@@ -312,7 +312,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'subsystem'");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_scan_subsystems(udev_enumerate);
enumerate_print_list(udev_enumerate);
@@ -320,7 +320,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
log_info("enumerate 'property IF_FS_*=filesystem'");
udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
+ if (!udev_enumerate)
return -1;
udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem");
udev_enumerate_scan_devices(udev_enumerate);
@@ -433,19 +433,20 @@ static void test_util_resolve_subsys_kernel(void) {
}
static void test_list(void) {
- struct udev_list list = {};
+ _cleanup_(udev_list_freep) struct udev_list *list = NULL;
struct udev_list_entry *e;
/* empty list */
- udev_list_init(&list, false);
- assert_se(!udev_list_get_entry(&list));
+ assert_se(list = udev_list_new(false));
+ assert_se(!udev_list_get_entry(list));
+ list = udev_list_free(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(list = udev_list_new(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"));
@@ -462,14 +463,14 @@ static void test_list(void) {
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);
+ list = udev_list_free(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(list = udev_list_new(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"));
@@ -487,7 +488,6 @@ static void test_list(void) {
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);
}
static int parse_args(int argc, char *argv[], const char **syspath, const char **subsystem) {
diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c
new file mode 100644
index 0000000000..8deaf4eb0f
--- /dev/null
+++ b/src/test/test-load-fragment.c
@@ -0,0 +1,801 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <unistd.h>
+
+#include "all-units.h"
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "conf-parser.h"
+#include "fd-util.h"
+#include "format-util.h"
+#include "fs-util.h"
+#include "hashmap.h"
+#include "hostname-util.h"
+#include "install-printf.h"
+#include "install.h"
+#include "load-fragment.h"
+#include "macro.h"
+#include "memory-util.h"
+#include "rm-rf.h"
+#include "specifier.h"
+#include "string-util.h"
+#include "strv.h"
+#include "test-helper.h"
+#include "tests.h"
+#include "tmpfile-util.h"
+#include "user-util.h"
+
+static int test_unit_file_get_set(void) {
+ int r;
+ Hashmap *h;
+ Iterator i;
+ UnitFileList *p;
+
+ h = hashmap_new(&string_hash_ops);
+ assert_se(h);
+
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
+ 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");
+ if (r < 0)
+ return EXIT_FAILURE;
+
+ HASHMAP_FOREACH(p, h, i)
+ printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
+
+ unit_file_list_free(h);
+
+ return 0;
+}
+
+static void check_execcommand(ExecCommand *c,
+ const char* path,
+ const char* argv0,
+ const char* argv1,
+ const char* argv2,
+ bool ignore) {
+ size_t n;
+
+ assert_se(c);
+ log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
+ path, argv0 ?: path, argv1, argv2);
+ n = strv_length(c->argv);
+ log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
+ c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
+ assert_se(streq(c->path, path));
+ assert_se(streq(c->argv[0], argv0 ?: path));
+ if (n > 0)
+ assert_se(streq_ptr(c->argv[1], argv1));
+ if (n > 1)
+ assert_se(streq_ptr(c->argv[2], argv2));
+ assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
+}
+
+static void test_config_parse_exec(void) {
+ /* int config_parse_exec(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+ int r;
+
+ ExecCommand *c = NULL, *c1;
+ const char *ccc;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(unit_freep) Unit *u = NULL;
+
+ 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;
+ }
+
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ assert_se(u = unit_new(m, sizeof(Service)));
+
+ log_info("/* basic test */");
+ r = config_parse_exec(NULL, "fake", 1, "section", 1,
+ "LValue", 0, "/RValue r1",
+ &c, u);
+ assert_se(r >= 0);
+ check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
+
+ r = config_parse_exec(NULL, "fake", 2, "section", 1,
+ "LValue", 0, "/RValue///slashes r1///",
+ &c, u);
+
+ log_info("/* test slashes */");
+ assert_se(r >= 0);
+ c1 = c->command_next;
+ check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
+
+ log_info("/* trailing slash */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/RValue/ argv0 r1",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* honour_argv0 */");
+ r = config_parse_exec(NULL, "fake", 3, "section", 1,
+ "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
+
+ log_info("/* honour_argv0, no args */");
+ r = config_parse_exec(NULL, "fake", 3, "section", 1,
+ "LValue", 0, "@/RValue",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* no command, whitespace only, reset */");
+ r = config_parse_exec(NULL, "fake", 3, "section", 1,
+ "LValue", 0, " ",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c == NULL);
+
+ log_info("/* ignore && honour_argv0 */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "-@/RValue///slashes3 argv0a r1",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c;
+ check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
+
+ log_info("/* ignore && honour_argv0 */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "@-/RValue///slashes4 argv0b r1",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
+
+ log_info("/* ignore && ignore */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "--/RValue argv0 r1",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* ignore && ignore (2) */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "-@-/RValue argv0 r1",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ; "
+ "/goo/goo boo",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ c1 = c1->command_next;
+ check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
+
+ log_info("/* two semicolons in a row */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ; ; "
+ "/goo/goo boo",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ /* second command fails because the executable name is ";" */
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* trailing semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ; ",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* trailing semicolon, no whitespace */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ;",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
+
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* trailing semicolon in single quotes */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "-@/RValue argv0 r1 ';'",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
+
+ log_info("/* escaped semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/bin/find \\;",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+
+ log_info("/* escaped semicolon with following arg */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/sbin/find \\; /x",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/sbin/find", NULL, ";", "/x", false);
+
+ log_info("/* escaped semicolon as part of an expression */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/sbin/find \\;x",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/sbin/find", NULL, "\\;x", NULL, false);
+
+ log_info("/* encoded semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/bin/find \\073",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+
+ log_info("/* quoted semicolon */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/bin/find \";\"",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+
+ log_info("/* quoted semicolon with following arg */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/sbin/find \";\" /x",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/sbin/find", NULL, ";", "/x", false);
+
+ log_info("/* spaces in the filename */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH WITH SPACES/daemon\" -1 -2",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
+
+ log_info("/* spaces in the filename, no args */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH WITH SPACES/daemon -1 -2\"",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
+
+ log_info("/* spaces in the filename, everything quoted */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
+
+ log_info("/* escaped spaces in the filename */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
+
+ log_info("/* escaped spaces in the filename (2) */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1,
+ "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
+
+ for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
+ /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
+ char path[] = "/path\\X";
+ path[sizeof(path) - 2] = *ccc;
+
+ log_info("/* invalid character: \\%c */", *ccc);
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, path,
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+ }
+
+ log_info("/* valid character: \\s */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path\\s",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
+
+ log_info("/* quoted backslashes */");
+ r = config_parse_exec(NULL, "fake", 5, "section", 1,
+ "LValue", 0,
+ "/bin/grep '\\w+\\K'",
+ &c, u);
+ assert_se(r >= 0);
+ c1 = c1->command_next;
+ check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
+
+ log_info("/* trailing backslash: \\ */");
+ /* backslash is invalid */
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path\\",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* missing ending ' */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path 'foo",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* missing ending ' with trailing backslash */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "/path 'foo\\",
+ &c, u);
+ assert_se(r == -ENOEXEC);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* invalid space between modifiers */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "- /path",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* only modifiers, no path */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "-",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c1->command_next == NULL);
+
+ log_info("/* empty argument, reset */");
+ r = config_parse_exec(NULL, "fake", 4, "section", 1,
+ "LValue", 0, "",
+ &c, u);
+ assert_se(r == 0);
+ assert_se(c == NULL);
+
+ exec_command_free_list(c);
+}
+
+static void test_config_parse_log_extra_fields(void) {
+ /* int config_parse_log_extra_fields(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+
+ int r;
+
+ _cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(unit_freep) Unit *u = NULL;
+ ExecContext c = {};
+
+ 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;
+ }
+
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ assert_se(u = unit_new(m, sizeof(Service)));
+
+ log_info("/* %s – basic test */", __func__);
+ r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
+ "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
+ &c, u);
+ assert_se(r >= 0);
+ assert_se(c.n_log_extra_fields == 2);
+ assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
+ assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
+
+ log_info("/* %s – add some */", __func__);
+ r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
+ "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
+ &c, u);
+ assert_se(r >= 0);
+ assert_se(c.n_log_extra_fields == 4);
+ assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
+ assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
+ assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
+ assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
+
+ exec_context_dump(&c, stdout, " --> ");
+
+ log_info("/* %s – reset */", __func__);
+ r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
+ "LValue", 0, "",
+ &c, u);
+ assert_se(r >= 0);
+ assert_se(c.n_log_extra_fields == 0);
+
+ exec_context_free_log_extra_fields(&c);
+
+ log_info("/* %s – bye */", __func__);
+}
+
+static void test_install_printf(void) {
+ char name[] = "name.service",
+ path[] = "/run/systemd/system/name.service";
+ UnitFileInstallInfo i = { .name = name, .path = path, };
+ UnitFileInstallInfo i2 = { .name= name, .path = path, };
+ char name3[] = "name@inst.service",
+ path3[] = "/run/systemd/system/name.service";
+ UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
+ UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
+
+ _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);
+
+#define expect(src, pattern, result) \
+ do { \
+ _cleanup_free_ char *t = NULL; \
+ _cleanup_free_ char \
+ *d1 = strdup(i.name), \
+ *d2 = strdup(i.path); \
+ assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
+ memzero(i.name, strlen(i.name)); \
+ memzero(i.path, strlen(i.path)); \
+ assert_se(d1 && d2); \
+ if (result) { \
+ printf("%s\n", t); \
+ assert_se(streq(t, result)); \
+ } else assert_se(t == NULL); \
+ strcpy(i.name, d1); \
+ strcpy(i.path, d2); \
+ } while (false)
+
+ expect(i, "%n", "name.service");
+ expect(i, "%N", "name");
+ 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);
+
+ expect(i, "%m", mid);
+ 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);
+
+ expect(i3, "%m", mid);
+ expect(i3, "%b", bid);
+ expect(i3, "%H", host);
+
+ expect(i4, "%g", group);
+ expect(i4, "%G", gid);
+ expect(i4, "%u", user);
+ expect(i4, "%U", uid);
+}
+
+static uint64_t make_cap(int cap) {
+ return ((uint64_t) 1ULL << (uint64_t) cap);
+}
+
+static void test_config_parse_capability_set(void) {
+ /* int config_parse_capability_set(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+ int r;
+ uint64_t capability_bounding_set = 0;
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_RAW",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == UINT64_C(0));
+
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "~",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(cap_test_all(capability_bounding_set));
+
+ capability_bounding_set = 0;
+ r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
+ &capability_bounding_set, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+}
+
+static void test_config_parse_rlimit(void) {
+ struct rlimit * rl[_RLIMIT_MAX] = {};
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+ rl[RLIMIT_NOFILE]->rlim_cur = 10;
+ rl[RLIMIT_NOFILE]->rlim_max = 20;
+
+ /* Invalid values don't change rl */
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_NOFILE]);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+ assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+ rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
+ assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_CPU]);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
+ assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
+
+ rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ assert_se(rl[RLIMIT_RTTIME]);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
+ assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+ rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
+}
+
+static void test_config_parse_pass_environ(void) {
+ /* int config_parse_pass_environ(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+ int r;
+ _cleanup_strv_free_ char **passenv = NULL;
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "A B",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 2);
+ assert_se(streq(passenv[0], "A"));
+ assert_se(streq(passenv[1], "B"));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_isempty(passenv));
+
+ r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
+ "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
+ &passenv, NULL);
+ assert_se(r >= 0);
+ assert_se(strv_length(passenv) == 1);
+ assert_se(streq(passenv[0], "normal_name"));
+
+}
+
+static void test_unit_dump_config_items(void) {
+ unit_dump_config_items(stdout);
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ int r;
+
+ test_setup_logging(LOG_INFO);
+
+ r = enter_cgroup_subroot();
+ if (r == -ENOMEDIUM)
+ return log_tests_skipped("cgroupfs not available");
+
+ assert_se(runtime_dir = setup_fake_runtime_dir());
+
+ r = test_unit_file_get_set();
+ test_config_parse_exec();
+ test_config_parse_log_extra_fields();
+ test_config_parse_capability_set();
+ test_config_parse_rlimit();
+ test_config_parse_pass_environ();
+ TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
+ test_unit_dump_config_items();
+
+ return r;
+}
diff --git a/src/test/test-local-addresses.c b/src/test/test-local-addresses.c
new file mode 100644
index 0000000000..37505ea783
--- /dev/null
+++ b/src/test/test-local-addresses.c
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio.h>
+
+#include "af-list.h"
+#include "alloc-util.h"
+#include "in-addr-util.h"
+#include "local-addresses.h"
+#include "tests.h"
+
+static void print_local_addresses(struct local_address *a, unsigned n) {
+ unsigned i;
+
+ for (i = 0; i < n; i++) {
+ _cleanup_free_ char *b = NULL;
+
+ assert_se(in_addr_to_string(a[i].family, &a[i].address, &b) >= 0);
+ printf("%s if%i scope=%i metric=%u address=%s\n", af_to_name(a[i].family), a[i].ifindex, a[i].scope, a[i].metric, b);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ struct local_address *a;
+ int n;
+
+ test_setup_logging(LOG_DEBUG);
+
+ a = NULL;
+ n = local_addresses(NULL, 0, AF_UNSPEC, &a);
+ assert_se(n >= 0);
+
+ printf("Local Addresses:\n");
+ print_local_addresses(a, (unsigned) n);
+ a = mfree(a);
+
+ n = local_gateways(NULL, 0, AF_UNSPEC, &a);
+ assert_se(n >= 0);
+
+ printf("Local Gateways:\n");
+ print_local_addresses(a, (unsigned) n);
+ free(a);
+
+ return 0;
+}
diff --git a/src/test/test-log.c b/src/test/test-log.c
index 18ef56ac39..c1f2f8b09d 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -6,6 +6,7 @@
#include "format-util.h"
#include "log.h"
#include "process-util.h"
+#include "string-util.h"
#include "util.h"
assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
@@ -26,6 +27,14 @@ assert_cc(!IS_SYNTHETIC_ERRNO(0));
#define X100(x) X10(X10(x))
#define X1000(x) X100(X10(x))
+static void test_file(void) {
+ log_info("__FILE__: %s", __FILE__);
+ log_info("RELATIVE_SOURCE_PATH: %s", RELATIVE_SOURCE_PATH);
+ log_info("PROJECT_FILE: %s", PROJECT_FILE);
+
+ assert(startswith(__FILE__, RELATIVE_SOURCE_PATH "/"));
+}
+
static void test_log_struct(void) {
log_struct(LOG_INFO,
"MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),
@@ -68,6 +77,8 @@ static void test_log_syntax(void) {
int main(int argc, char* argv[]) {
int target;
+ test_file();
+
for (target = 0; target < _LOG_TARGET_MAX; target++) {
log_set_target(target);
log_open();
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index d3dbb54ca1..e9233a1643 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -75,7 +75,8 @@ int main(int argc, char *argv[]) {
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
0,
- 0);
+ 0,
+ NULL);
if (r < 0) {
log_error_errno(r, "Failed to setup namespace: %m");
diff --git a/src/test/test-nss.c b/src/test/test-nss.c
index 27afe36082..6ba0f6887e 100644
--- a/src/test/test-nss.c
+++ b/src/test/test-nss.c
@@ -8,6 +8,7 @@
#include "af-list.h"
#include "alloc-util.h"
#include "errno-list.h"
+#include "format-util.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
@@ -77,7 +78,7 @@ static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
union in_addr_union u;
int r;
char family_name[DECIMAL_STR_MAX(int)];
- char ifname[IF_NAMESIZE];
+ char ifname[IF_NAMESIZE + 1];
memcpy(&u, it->addr, 16);
r = in_addr_to_string(it->family, &u, &a);
@@ -88,7 +89,7 @@ static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
if (it->scopeid == 0)
goto numerical_index;
- if (if_indextoname(it->scopeid, ifname) == NULL) {
+ if (!format_ifname(it->scopeid, ifname)) {
log_warning_errno(errno, "if_indextoname(%d) failed: %m", it->scopeid);
numerical_index:
xsprintf(ifname, "%i", it->scopeid);
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
index f208559358..62ebc9c923 100644
--- a/src/test/test-path-lookup.c
+++ b/src/test/test-path-lookup.c
@@ -22,15 +22,15 @@ static void test_paths(UnitFileScope scope) {
assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0);
assert_se(lookup_paths_init(&lp_without_env, scope, 0, NULL) >= 0);
assert_se(!strv_isempty(lp_without_env.search_path));
- assert_se(lookup_paths_reduce(&lp_without_env) >= 0);
+ lookup_paths_log(&lp_without_env);
systemd_unit_path = strjoina(template, "/systemd-unit-path");
assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0);
assert_se(lookup_paths_init(&lp_with_env, scope, 0, NULL) == 0);
assert_se(strv_length(lp_with_env.search_path) == 1);
assert_se(streq(lp_with_env.search_path[0], systemd_unit_path));
- assert_se(lookup_paths_reduce(&lp_with_env) >= 0);
- assert_se(strv_isempty(lp_with_env.search_path));
+ lookup_paths_log(&lp_with_env);
+ assert_se(strv_equal(lp_with_env.search_path, STRV_MAKE(systemd_unit_path)));
assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 182991695a..ece3eb427c 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -25,6 +25,8 @@
static void test_path_simplify(const char *in, const char *out, const char *out_dot) {
char *p;
+ log_info("/* %s */", __func__);
+
p = strdupa(in);
assert_se(streq(path_simplify(p, false), out));
@@ -35,6 +37,8 @@ static void test_path_simplify(const char *in, const char *out, const char *out_
static void test_path(void) {
_cleanup_close_ int fd = -1;
+ log_info("/* %s */", __func__);
+
test_path_compare("/goo", "/goo", 0);
test_path_compare("/goo", "/goo", 0);
test_path_compare("//goo", "/goo", 0);
@@ -114,6 +118,8 @@ static void test_path(void) {
static void test_path_equal_root(void) {
/* Nail down the details of how path_equal("/", ...) works. */
+ log_info("/* %s */", __func__);
+
assert_se(path_equal("/", "/"));
assert_se(path_equal("/", "//"));
@@ -156,6 +162,8 @@ static void test_path_equal_root(void) {
static void test_find_binary(const char *self) {
char *p;
+ log_info("/* %s */", __func__);
+
assert_se(find_binary("/bin/sh", &p) == 0);
puts(p);
assert_se(path_equal(p, "/bin/sh"));
@@ -191,6 +199,8 @@ static void test_prefixes(void) {
char s[PATH_MAX];
bool b;
+ log_info("/* %s */", __func__);
+
i = 0;
PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
log_error("---%s---", s);
@@ -238,6 +248,7 @@ static void test_prefixes(void) {
}
static void test_path_join(void) {
+ log_info("/* %s */", __func__);
#define test_join(expected, ...) { \
_cleanup_free_ char *z = NULL; \
@@ -283,6 +294,8 @@ static void test_path_join(void) {
}
static void test_fsck_exists(void) {
+ log_info("/* %s */", __func__);
+
/* Ensure we use a sane default for PATH. */
unsetenv("PATH");
@@ -296,6 +309,8 @@ static void test_fsck_exists(void) {
static void test_make_relative(void) {
char *result;
+ log_info("/* %s */", __func__);
+
assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
assert_se(path_make_relative("/some/dotdot/../path", "/some/path", &result) < 0);
@@ -327,7 +342,7 @@ static void test_strv_resolve(void) {
search_dirs = strv_new("/dir1", "/dir2", "/dir3");
assert_se(search_dirs);
STRV_FOREACH(d, search_dirs) {
- char *p = strappend(tmp_dir, *d);
+ char *p = path_join(tmp_dir, *d);
assert_se(p);
assert_se(strv_push(&absolute_dirs, p) == 0);
}
@@ -347,6 +362,8 @@ static void test_strv_resolve(void) {
static void test_path_startswith(void) {
const char *p;
+ log_info("/* %s */", __func__);
+
p = path_startswith("/foo/bar/barfoo/", "/foo");
assert_se(streq_ptr(p, "bar/barfoo/"));
@@ -388,21 +405,26 @@ static void test_prefix_root_one(const char *r, const char *p, const char *expec
_cleanup_free_ char *s = NULL;
const char *t;
- assert_se(s = prefix_root(r, p));
- assert_se(streq_ptr(s, expected));
+ assert_se(s = path_join(r, p));
+ assert_se(path_equal_ptr(s, expected));
t = prefix_roota(r, p);
assert_se(t);
- assert_se(streq_ptr(t, expected));
+ assert_se(path_equal_ptr(t, expected));
}
static void test_prefix_root(void) {
+ log_info("/* %s */", __func__);
+
test_prefix_root_one("/", "/foo", "/foo");
test_prefix_root_one(NULL, "/foo", "/foo");
test_prefix_root_one("", "/foo", "/foo");
test_prefix_root_one("///", "/foo", "/foo");
test_prefix_root_one("/", "////foo", "/foo");
test_prefix_root_one(NULL, "////foo", "/foo");
+ test_prefix_root_one("/", "foo", "/foo");
+ test_prefix_root_one("", "foo", "foo");
+ test_prefix_root_one(NULL, "foo", "foo");
test_prefix_root_one("/foo", "/bar", "/foo/bar");
test_prefix_root_one("/foo", "bar", "/foo/bar");
@@ -415,6 +437,8 @@ static void test_prefix_root(void) {
static void test_file_in_same_dir(void) {
char *t;
+ log_info("/* %s */", __func__);
+
t = file_in_same_dir("/", "a");
assert_se(streq(t, "/a"));
free(t);
@@ -461,12 +485,14 @@ static void test_path_extract_filename_one(const char *input, const char *output
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));
+ log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror_safe(r), strnull(output), strerror_safe(ret));
assert_se(streq_ptr(k, output));
assert_se(r == ret);
}
static void test_path_extract_filename(void) {
+ log_info("/* %s */", __func__);
+
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);
@@ -499,6 +525,8 @@ static void test_filename_is_valid(void) {
char foo[FILENAME_MAX+2];
int i;
+ log_info("/* %s */", __func__);
+
assert_se(!filename_is_valid(""));
assert_se(!filename_is_valid("/bar/foo"));
assert_se(!filename_is_valid("/"));
@@ -516,6 +544,8 @@ static void test_filename_is_valid(void) {
}
static void test_hidden_or_backup_file(void) {
+ log_info("/* %s */", __func__);
+
assert_se(hidden_or_backup_file(".hidden"));
assert_se(hidden_or_backup_file("..hidden"));
assert_se(!hidden_or_backup_file("hidden."));
@@ -541,6 +571,8 @@ static void test_systemd_installation_has_version(const char *path) {
const unsigned versions[] = {0, 231, PROJECT_VERSION, 999};
unsigned i;
+ log_info("/* %s */", __func__);
+
for (i = 0; i < ELEMENTSOF(versions); i++) {
r = systemd_installation_has_version(path, versions[i]);
assert_se(r >= 0);
@@ -550,6 +582,7 @@ static void test_systemd_installation_has_version(const char *path) {
}
static void test_skip_dev_prefix(void) {
+ log_info("/* %s */", __func__);
assert_se(streq(skip_dev_prefix("/"), "/"));
assert_se(streq(skip_dev_prefix("/dev"), ""));
@@ -565,6 +598,8 @@ static void test_skip_dev_prefix(void) {
}
static void test_empty_or_root(void) {
+ log_info("/* %s */", __func__);
+
assert_se(empty_or_root(NULL));
assert_se(empty_or_root(""));
assert_se(empty_or_root("/"));
@@ -578,6 +613,7 @@ static void test_empty_or_root(void) {
}
static void test_path_startswith_set(void) {
+ log_info("/* %s */", __func__);
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"));
@@ -598,6 +634,28 @@ static void test_path_startswith_set(void) {
assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL));
}
+static void test_path_startswith_strv(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), ""));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL));
+
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar2"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar2"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar2"));
+ assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "", "/zzz")), NULL));
+
+ assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL));
+ assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), NULL));
+ assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), NULL));
+ assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo2/bar"));
+ assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL));
+}
+
int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
@@ -619,6 +677,7 @@ int main(int argc, char **argv) {
test_skip_dev_prefix();
test_empty_or_root();
test_path_startswith_set();
+ test_path_startswith_strv();
test_systemd_installation_has_version(argv[1]); /* NULL is OK */
diff --git a/src/test/test-pretty-print.c b/src/test/test-pretty-print.c
index 3ad80d145d..9236eb1315 100644
--- a/src/test/test-pretty-print.c
+++ b/src/test/test-pretty-print.c
@@ -15,7 +15,7 @@ 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);
+ printf("Hey, consider visiting the %s right now! It is very good!\n", formatted);
formatted = mfree(formatted);
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
index 4e209de5b6..6d25a6919e 100644
--- a/src/test/test-proc-cmdline.c
+++ b/src/test/test-proc-cmdline.c
@@ -170,7 +170,6 @@ static void test_proc_cmdline_get_key_many(void) {
"doubleticks", &value6,
"zummm", &value7) == 5);
-
assert_se(streq_ptr(value1, "quux"));
assert_se(!value2);
assert_se(streq_ptr(value3, "tuet"));
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 89f6618e2e..8dc9fdda50 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -48,14 +48,14 @@ static void test_get_process_comm(pid_t pid) {
} else
log_warning("%s not exist.", path);
- assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
+ assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
- assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
+ assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0);
log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
free(d);
- assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
+ assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0);
log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
assert_se(get_process_ppid(pid, &e) >= 0);
@@ -107,12 +107,12 @@ static void test_get_process_comm_escape(void) {
test_get_process_comm_escape_one("foo", "foo");
test_get_process_comm_escape_one("012345678901234", "012345678901234");
test_get_process_comm_escape_one("0123456789012345", "012345678901234");
- test_get_process_comm_escape_one("äöüß", "\\303\\244\\303…");
- test_get_process_comm_escape_one("xäöüß", "x\\303\\244…");
- test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244…");
- test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244…");
- test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244…");
- test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303…");
+ test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237");
+ test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237");
+ test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237");
+ test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237");
+ test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
+ test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
assert_se(prctl(PR_SET_NAME, saved) >= 0);
}
@@ -237,150 +237,149 @@ static void test_get_process_cmdline_harder(void) {
assert_se(prctl(PR_SET_NAME, "testa") >= 0);
- assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
- assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ log_info("'%s'", line);
assert_se(streq(line, ""));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
- assert_se(streq(line, "["));
+ assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
- assert_se(streq(line, "[."));
+ assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
- assert_se(streq(line, "[.."));
+ assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[t…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
- assert_se(streq(line, "[..."));
+ assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[te…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
- assert_se(streq(line, "[...]"));
+ assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[tes…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
- assert_se(streq(line, "[t...]"));
+ assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[test…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
- assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
-
- assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
-
- assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
- assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
+ assert_se(write(fd, "foo\0bar", 8) == 8);
- assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
+ log_info("'%s'", line);
assert_se(streq(line, "foo bar"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "foo bar"));
line = mfree(line);
assert_se(write(fd, "quux", 4) == 4);
- assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
+ log_info("'%s'", line);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
- assert_se(streq(line, ""));
+ assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
- assert_se(streq(line, "."));
+ assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "f…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
- assert_se(streq(line, ".."));
+ assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "fo…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
- assert_se(streq(line, "..."));
+ assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
- assert_se(streq(line, "f..."));
+ assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo …"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
- assert_se(streq(line, "fo..."));
+ assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo b…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
- assert_se(streq(line, "foo..."));
+ assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo ba…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
- assert_se(streq(line, "foo..."));
+ assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo bar…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0);
- assert_se(streq(line, "foo b..."));
+ assert_se(get_process_cmdline(getpid_cached(), 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo bar …"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
- assert_se(streq(line, "foo ba..."));
+ assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo bar q…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
- assert_se(streq(line, "foo bar..."));
+ assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo bar qu…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
- assert_se(streq(line, "foo bar..."));
+ assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
- assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
- assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
assert_se(streq(line, "[aaaa bbbb cccc]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
- assert_se(streq(line, "[aaaa...]"));
+ assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[aaaa bbb…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
- assert_se(streq(line, "[aaaa...]"));
+ assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[aaaa bbbb…"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
- assert_se(streq(line, "[aaaa b...]"));
+ assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+ assert_se(streq(line, "[aaaa bbbb …"));
line = mfree(line);
safe_close(fd);
@@ -408,8 +407,10 @@ static void test_rename_process_now(const char *p, int ret) {
assert_se(get_process_comm(0, &comm) >= 0);
log_info("comm = <%s>", comm);
assert_se(strneq(comm, p, TASK_COMM_LEN-1));
+ /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
+ * future. We'd only check the initial part, at least until we recompile, but this will still pass. */
- r = get_process_cmdline(0, 0, false, &cmdline);
+ r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
assert_se(r >= 0);
/* we cannot expect cmdline to be renamed properly without privileges */
if (geteuid() == 0) {
@@ -523,14 +524,14 @@ static void test_getpid_measure(void) {
(void) getpid();
q = now(CLOCK_MONOTONIC) - t;
- log_info(" glibc getpid(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
+ log_info(" glibc getpid(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
t = now(CLOCK_MONOTONIC);
for (i = 0; i < MEASURE_ITERATIONS; i++)
(void) getpid_cached();
q = now(CLOCK_MONOTONIC) - t;
- log_info("getpid_cached(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
+ log_info("getpid_cached(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
}
static void test_safe_fork(void) {
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
index 1d0612985b..662688e0f0 100644
--- a/src/test/test-procfs-util.c
+++ b/src/test/test-procfs-util.c
@@ -2,8 +2,8 @@
#include <errno.h>
+#include "format-util.h"
#include "log.h"
-#include "parse-util.h"
#include "procfs-util.h"
int main(int argc, char *argv[]) {
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index 9b7307cf39..a906070f9a 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -635,7 +635,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, true) >= 0);
+ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0);
assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0);
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
index 35b087653e..7fc16a62b6 100644
--- a/src/test/test-sizeof.c
+++ b/src/test/test-sizeof.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <sched.h>
#include <stdio.h>
#include <string.h>
@@ -65,6 +66,8 @@ int main(void) {
info(uid_t);
info(gid_t);
+ info(__cpu_mask);
+
info(enum Enum);
info(enum BigEnum);
info(enum BigEnum2);
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index e0c513ad8c..014b1aa7a2 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -7,6 +7,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include "errno-util.h"
#include "fd-util.h"
#include "log.h"
#include "memory-util.h"
@@ -16,12 +17,29 @@
#include "util.h"
static void test_parse_sleep_config(void) {
- const char *verb;
-
+ _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
log_info("/* %s */", __func__);
- FOREACH_STRING(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")
- assert_se(parse_sleep_config(verb, NULL, NULL, NULL, NULL) == 0);
+ assert(parse_sleep_config(&sleep_config) == 0);
+
+ _cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys;
+
+ sum = strv_join(sleep_config->suspend_modes, ", ");
+ sus = strv_join(sleep_config->suspend_states, ", ");
+ him = strv_join(sleep_config->hibernate_modes, ", ");
+ his = strv_join(sleep_config->hibernate_states, ", ");
+ hym = strv_join(sleep_config->hybrid_modes, ", ");
+ hys = strv_join(sleep_config->hybrid_states, ", ");
+ log_debug(" allow_suspend: %u", sleep_config->allow_suspend);
+ log_debug(" allow_hibernate: %u", sleep_config->allow_hibernate);
+ log_debug(" allow_s2h: %u", sleep_config->allow_s2h);
+ log_debug(" allow_hybrid_sleep: %u", sleep_config->allow_hybrid_sleep);
+ log_debug(" suspend modes: %s", sum);
+ log_debug(" states: %s", sus);
+ log_debug(" hibernate modes: %s", him);
+ log_debug(" states: %s", his);
+ log_debug(" hybrid modes: %s", hym);
+ log_debug(" states: %s", hys);
}
static int test_fiemap(const char *path) {
@@ -61,7 +79,7 @@ static void test_sleep(void) {
**reboot = strv_new("reboot"),
**platform = strv_new("platform"),
**shutdown = strv_new("shutdown"),
- **freez = strv_new("freeze");
+ **freeze = strv_new("freeze");
int r;
log_info("/* %s */", __func__);
@@ -74,23 +92,23 @@ static void test_sleep(void) {
log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0));
log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0));
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("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0));
log_info("/= running system =/");
r = can_sleep("suspend");
- log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("hibernate");
- log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("hybrid-sleep");
- log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("suspend-then-hibernate");
- log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
}
int main(int argc, char* argv[]) {
int i, r = 0, k;
- test_setup_logging(LOG_INFO);
+ test_setup_logging(LOG_DEBUG);
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 057840d76f..4e9a0bddf4 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -810,6 +810,67 @@ static void test_send_emptydata(void) {
assert_se(fd == -999);
}
+static void test_flush_accept(void) {
+ _cleanup_close_ int listen_stream = -1, listen_dgram = -1, listen_seqpacket = 1, connect_stream = -1, connect_dgram = -1, connect_seqpacket = -1;
+ static const union sockaddr_union sa = { .un.sun_family = AF_UNIX };
+ union sockaddr_union lsa;
+ socklen_t l;
+
+ listen_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_stream >= 0);
+
+ listen_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_dgram >= 0);
+
+ listen_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_seqpacket >= 0);
+
+ assert_se(flush_accept(listen_stream) < 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) < 0);
+
+ assert_se(bind(listen_stream, &sa.sa, sizeof(sa_family_t)) >= 0);
+ assert_se(bind(listen_dgram, &sa.sa, sizeof(sa_family_t)) >= 0);
+ assert_se(bind(listen_seqpacket, &sa.sa, sizeof(sa_family_t)) >= 0);
+
+ assert_se(flush_accept(listen_stream) < 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) < 0);
+
+ assert_se(listen(listen_stream, SOMAXCONN) >= 0);
+ assert_se(listen(listen_dgram, SOMAXCONN) < 0);
+ assert_se(listen(listen_seqpacket, SOMAXCONN) >= 0);
+
+ assert_se(flush_accept(listen_stream) >= 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) >= 0);
+
+ connect_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_stream >= 0);
+
+ connect_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_dgram >= 0);
+
+ connect_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_seqpacket >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_stream, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_stream, &lsa.sa, l) >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_dgram, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_dgram, &lsa.sa, l) >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_seqpacket, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_seqpacket, &lsa.sa, l) >= 0);
+
+ assert_se(flush_accept(listen_stream) >= 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@@ -843,6 +904,7 @@ int main(int argc, char *argv[]) {
test_receive_nopassfd();
test_send_nodata_nofd();
test_send_emptydata();
+ test_flush_accept();
return 0;
}
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 064a5abdac..8ea3994366 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -9,29 +9,6 @@
#include "utf8.h"
#include "util.h"
-static void test_string_erase(void) {
- char *x;
-
- x = strdupa("");
- assert_se(streq(string_erase(x), ""));
-
- x = strdupa("1");
- assert_se(streq(string_erase(x), ""));
-
- x = strdupa("123456789");
- assert_se(streq(string_erase(x), ""));
-
- assert_se(x[1] == '\0');
- assert_se(x[2] == '\0');
- assert_se(x[3] == '\0');
- assert_se(x[4] == '\0');
- assert_se(x[5] == '\0');
- assert_se(x[6] == '\0');
- assert_se(x[7] == '\0');
- assert_se(x[8] == '\0');
- 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;
@@ -273,22 +250,6 @@ static void test_strrep(void) {
assert_se(streq(zero, ""));
}
-static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
-
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
-
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
-
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
-
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
-}
-
static void test_string_has_cc(void) {
assert_se(string_has_cc("abc\1", NULL));
assert_se(string_has_cc("abc\x7f", NULL));
@@ -380,7 +341,7 @@ static void check(const char *test, char** expected, bool trailing) {
for (;;) {
_cleanup_free_ char *word = NULL;
- r = extract_first_word(&test, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&test, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0) {
assert_se(!trailing);
break;
@@ -582,7 +543,6 @@ static void test_memory_startswith_no_case(void) {
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();
@@ -592,7 +552,6 @@ int main(int argc, char *argv[]) {
test_strextend();
test_strextend_with_separator();
test_strrep();
- test_strappend();
test_string_has_cc();
test_ascii_strlower();
test_strshorten();
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index 18ad03669c..5e96f3a8a7 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -23,6 +23,8 @@ static void test_specifier_printf(void) {
_cleanup_free_ char *w = NULL;
int r;
+ log_info("/* %s */", __func__);
+
r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w);
assert_se(r >= 0);
assert_se(w);
@@ -38,6 +40,8 @@ static void test_specifier_printf(void) {
}
static void test_str_in_set(void) {
+ log_info("/* %s */", __func__);
+
assert_se(STR_IN_SET("x", "x", "y", "z"));
assert_se(!STR_IN_SET("X", "x", "y", "z"));
assert_se(!STR_IN_SET("", "x", "y", "z"));
@@ -45,6 +49,8 @@ static void test_str_in_set(void) {
}
static void test_strptr_in_set(void) {
+ log_info("/* %s */", __func__);
+
assert_se(STRPTR_IN_SET("x", "x", "y", "z"));
assert_se(!STRPTR_IN_SET("X", "x", "y", "z"));
assert_se(!STRPTR_IN_SET("", "x", "y", "z"));
@@ -57,6 +63,8 @@ static void test_strptr_in_set(void) {
}
static void test_startswith_set(void) {
+ log_info("/* %s */", __func__);
+
assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo"));
assert_se(!STARTSWITH_SET("foo", "bar"));
@@ -105,11 +113,15 @@ static const char* const input_table_one_empty[] = {
};
static void test_strv_find(void) {
+ log_info("/* %s */", __func__);
+
assert_se(strv_find((char **)input_table_multiple, "three"));
assert_se(!strv_find((char **)input_table_multiple, "four"));
}
static void test_strv_find_prefix(void) {
+ log_info("/* %s */", __func__);
+
assert_se(strv_find_prefix((char **)input_table_multiple, "o"));
assert_se(strv_find_prefix((char **)input_table_multiple, "one"));
assert_se(strv_find_prefix((char **)input_table_multiple, ""));
@@ -120,6 +132,8 @@ static void test_strv_find_prefix(void) {
static void test_strv_find_startswith(void) {
char *r;
+ log_info("/* %s */", __func__);
+
r = strv_find_startswith((char **)input_table_multiple, "o");
assert_se(r && streq(r, "ne"));
@@ -136,6 +150,8 @@ static void test_strv_find_startswith(void) {
static void test_strv_join(void) {
_cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
+ log_info("/* %s */", __func__);
+
p = strv_join((char **)input_table_multiple, ", ");
assert_se(p);
assert_se(streq(p, "one, two, three"));
@@ -168,6 +184,8 @@ static void test_strv_join(void) {
static void test_strv_join_prefix(void) {
_cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
+ log_info("/* %s */", __func__);
+
p = strv_join_prefix((char **)input_table_multiple, ", ", "foo");
assert_se(p);
assert_se(streq(p, "fooone, footwo, foothree"));
@@ -204,7 +222,9 @@ static void test_strv_unquote(const char *quoted, char **list) {
char **t;
int r;
- r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES);
+ log_info("/* %s */", __func__);
+
+ r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
assert_se(r == (int) strv_length(list));
assert_se(s);
j = strv_join(s, " | ");
@@ -221,66 +241,70 @@ static void test_invalid_unquote(const char *quoted) {
char **s = NULL;
int r;
- r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES);
+ log_info("/* %s */", __func__);
+
+ r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
assert_se(s == NULL);
assert_se(r == -EINVAL);
}
static void test_strv_split(void) {
- _cleanup_strv_free_ char **l = NULL;
+ _cleanup_(strv_free_erasep) char **l = NULL;
const char str[] = "one,two,three";
+ log_info("/* %s */", __func__);
+
l = strv_split(str, ",");
assert_se(l);
assert_se(strv_equal(l, (char**) input_table_multiple));
- strv_free(l);
+ strv_free_erase(l);
l = strv_split(" one two\t three", WHITESPACE);
assert_se(l);
assert_se(strv_equal(l, (char**) input_table_multiple));
- strv_free(l);
+ strv_free_erase(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);
+ strv_free_erase(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);
+ strv_free_erase(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);
+ strv_free_erase(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);
+ strv_free_erase(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);
+ strv_free_erase(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);
+ strv_free_erase(l);
l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(l);
@@ -290,6 +314,8 @@ static void test_strv_split(void) {
static void test_strv_split_empty(void) {
_cleanup_strv_free_ char **l = NULL;
+ log_info("/* %s */", __func__);
+
l = strv_split("", WHITESPACE);
assert_se(l);
assert_se(strv_isempty(l));
@@ -355,6 +381,8 @@ static void test_strv_split_extract(void) {
const char *str = ":foo\\:bar::waldo:";
int r;
+ log_info("/* %s */", __func__);
+
r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
assert_se(r == (int) strv_length(l));
assert_se(streq_ptr(l[0], ""));
@@ -371,8 +399,9 @@ static void test_strv_split_newlines(void) {
_cleanup_strv_free_ char **l = NULL;
const char str[] = "one\ntwo\nthree";
- l = strv_split_newlines(str);
+ log_info("/* %s */", __func__);
+ l = strv_split_newlines(str);
assert_se(l);
STRV_FOREACH(s, l) {
@@ -384,6 +413,8 @@ static void test_strv_split_nulstr(void) {
_cleanup_strv_free_ char **l = NULL;
const char nulstr[] = "str0\0str1\0str2\0str3\0";
+ log_info("/* %s */", __func__);
+
l = strv_split_nulstr (nulstr);
assert_se(l);
@@ -397,6 +428,8 @@ static void test_strv_parse_nulstr(void) {
_cleanup_strv_free_ char **l = NULL;
const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx";
+ log_info("/* %s */", __func__);
+
l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
assert_se(l);
puts("Parse nulstr:");
@@ -429,6 +462,8 @@ static void test_strv_overlap(void) {
NULL
};
+ log_info("/* %s */", __func__);
+
assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
}
@@ -443,6 +478,8 @@ static void test_strv_sort(void) {
NULL
};
+ log_info("/* %s */", __func__);
+
strv_sort((char **)input_table);
assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
@@ -455,6 +492,8 @@ static void test_strv_sort(void) {
static void test_strv_extend_strv_concat(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
+ log_info("/* %s */", __func__);
+
a = strv_new("without", "suffix");
b = strv_new("with", "suffix");
assert_se(a);
@@ -471,6 +510,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;
+ log_info("/* %s */", __func__);
+
a = strv_new("abc", "def", "ghi");
b = strv_new("jkl", "mno", "abc", "pqr");
assert_se(a);
@@ -497,6 +538,8 @@ static void test_strv_extend_strv(void) {
static void test_strv_extend(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
+ log_info("/* %s */", __func__);
+
a = strv_new("test", "test1");
assert_se(a);
assert_se(strv_extend(&a, "test2") >= 0);
@@ -511,6 +554,8 @@ static void test_strv_extend(void) {
static void test_strv_extendf(void) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
+ log_info("/* %s */", __func__);
+
a = strv_new("test", "test1");
assert_se(a);
assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
@@ -527,13 +572,13 @@ static void test_strv_foreach(void) {
unsigned i = 0;
char **check;
- a = strv_new("one", "two", "three");
+ log_info("/* %s */", __func__);
+ a = strv_new("one", "two", "three");
assert_se(a);
- STRV_FOREACH(check, a) {
+ STRV_FOREACH(check, a)
assert_se(streq(*check, input_table_multiple[i++]));
- }
}
static void test_strv_foreach_backwards(void) {
@@ -541,6 +586,8 @@ static void test_strv_foreach_backwards(void) {
unsigned i = 2;
char **check;
+ log_info("/* %s */", __func__);
+
a = strv_new("one", "two", "three");
assert_se(a);
@@ -559,19 +606,21 @@ static void test_strv_foreach_pair(void) {
_cleanup_strv_free_ char **a = NULL;
char **x, **y;
+ log_info("/* %s */", __func__);
+
a = strv_new("pair_one", "pair_one",
"pair_two", "pair_two",
"pair_three", "pair_three");
-
- STRV_FOREACH_PAIR(x, y, a) {
+ STRV_FOREACH_PAIR(x, y, a)
assert_se(streq(*x, *y));
- }
}
static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
char **j;
unsigned i;
+ log_info("/* %s */", __func__);
+
j = strv_from_stdarg_alloca(first);
for (i = 0;; i++) {
@@ -583,6 +632,8 @@ static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
}
static void test_strv_from_stdarg_alloca(void) {
+ log_info("/* %s */", __func__);
+
test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
@@ -591,6 +642,8 @@ static void test_strv_from_stdarg_alloca(void) {
static void test_strv_insert(void) {
_cleanup_strv_free_ char **a = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(strv_insert(&a, 0, strdup("first")) == 0);
assert_se(streq(a[0], "first"));
assert_se(!a[1]);
@@ -621,6 +674,8 @@ static void test_strv_insert(void) {
static void test_strv_push_prepend(void) {
_cleanup_strv_free_ char **a = NULL;
+ log_info("/* %s */", __func__);
+
a = strv_new("foo", "bar", "three");
assert_se(strv_push_prepend(&a, strdup("first")) >= 0);
@@ -643,6 +698,8 @@ static void test_strv_push(void) {
_cleanup_strv_free_ char **a = NULL;
char *i, *j;
+ log_info("/* %s */", __func__);
+
assert_se(i = strdup("foo"));
assert_se(strv_push(&a, i) >= 0);
@@ -661,6 +718,8 @@ static void test_strv_equal(void) {
_cleanup_strv_free_ char **b = NULL;
_cleanup_strv_free_ char **c = NULL;
+ log_info("/* %s */", __func__);
+
a = strv_new("one", "two", "three");
assert_se(a);
b = strv_new("one", "two", "three");
@@ -680,6 +739,8 @@ 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;
+ log_info("/* %s */", __func__);
+
a = strv_new(NULL);
assert_se(a);
assert_se(strv_is_uniq(a));
@@ -700,6 +761,8 @@ 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;
+ log_info("/* %s */", __func__);
+
a = strv_new(NULL);
assert_se(a);
@@ -731,6 +794,8 @@ static void test_strv_reverse(void) {
static void test_strv_shell_escape(void) {
_cleanup_strv_free_ char **v = NULL;
+ log_info("/* %s */", __func__);
+
v = strv_new("foo:bar", "bar,baz", "wal\\do");
assert_se(v);
assert_se(strv_shell_escape(v, ",:"));
@@ -746,6 +811,8 @@ static void test_strv_skip_one(char **a, size_t n, char **b) {
}
static void test_strv_skip(void) {
+ log_info("/* %s */", __func__);
+
test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
@@ -765,6 +832,8 @@ static void test_strv_skip(void) {
static void test_strv_extend_n(void) {
_cleanup_strv_free_ char **v = NULL;
+ log_info("/* %s */", __func__);
+
v = strv_new("foo", "bar");
assert_se(v);
@@ -796,6 +865,8 @@ static void test_strv_make_nulstr_one(char **l) {
size_t n, m;
unsigned i = 0;
+ log_info("/* %s */", __func__);
+
assert_se(strv_make_nulstr(l, &b, &n) >= 0);
assert_se(q = strv_parse_nulstr(b, n));
assert_se(strv_equal(l, q));
@@ -810,6 +881,8 @@ static void test_strv_make_nulstr_one(char **l) {
}
static void test_strv_make_nulstr(void) {
+ log_info("/* %s */", __func__);
+
test_strv_make_nulstr_one(NULL);
test_strv_make_nulstr_one(STRV_MAKE(NULL));
test_strv_make_nulstr_one(STRV_MAKE("foo"));
@@ -820,6 +893,8 @@ static void test_strv_make_nulstr(void) {
static void test_strv_free_free(void) {
char ***t;
+ log_info("/* %s */", __func__);
+
assert_se(t = new(char**, 3));
assert_se(t[0] = strv_new("a", "b"));
assert_se(t[1] = strv_new("c", "d", "e"));
@@ -838,6 +913,8 @@ static void test_foreach_string(void) {
const char *x;
unsigned i = 0;
+ log_info("/* %s */", __func__);
+
FOREACH_STRING(x, "foo", "bar", "waldo")
assert_se(streq_ptr(t[i++], x));
@@ -850,6 +927,8 @@ static void test_foreach_string(void) {
static void test_strv_fnmatch(void) {
_cleanup_strv_free_ char **v = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0));
v = strv_new("*\\*");
diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c
index 21d56d9be6..d7199124a3 100644
--- a/src/test/test-strxcpyx.c
+++ b/src/test/test-strxcpyx.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <stdio.h>
#include <string.h>
#include "string-util.h"
@@ -78,6 +79,24 @@ static void test_strscpyl(void) {
assert_se(space_left == 10);
}
+static void test_sd_event_code_migration(void) {
+ char b[100 * DECIMAL_STR_MAX(unsigned) + 1];
+ char c[100 * DECIMAL_STR_MAX(unsigned) + 1], *p;
+ unsigned i;
+ size_t l;
+ int o;
+
+ for (i = o = 0; i < 100; i++)
+ o += snprintf(&b[o], sizeof(b) - o, "%u ", i);
+
+ p = c;
+ l = sizeof(c);
+ for (i = 0; i < 100; i++)
+ l = strpcpyf(&p, l, "%u ", i);
+
+ assert_se(streq(b, c));
+}
+
int main(int argc, char *argv[]) {
test_strpcpy();
test_strpcpyf();
@@ -85,5 +104,7 @@ int main(int argc, char *argv[]) {
test_strscpy();
test_strscpyl();
+ test_sd_event_code_migration();
+
return 0;
}
diff --git a/src/test/test-systemd-tmpfiles.py b/src/test/test-systemd-tmpfiles.py
index 83a66e8772..7f4af38940 100755
--- a/src/test/test-systemd-tmpfiles.py
+++ b/src/test/test-systemd-tmpfiles.py
@@ -52,8 +52,8 @@ def test_invalids(*, user):
test_line('w /unresolved/argument/sandwich - - - - "%v%Y%v"', user=user)
test_line('w /unresolved/filename/%Y - - - - "whatever"', user=user)
test_line('w /unresolved/filename/sandwich/%v%Y%v - - - - "whatever"', user=user)
- test_line('w - - - - - "no file specfied"', user=user)
- test_line('C - - - - - "no file specfied"', user=user)
+ test_line('w - - - - - "no file specified"', user=user)
+ test_line('C - - - - - "no file specified"', user=user)
test_line('C non/absolute/path - - - - -', user=user)
test_line('b - - - - - -', user=user)
test_line('b 1234 - - - - -', user=user)
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index 96d92279fb..0e563f5497 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -75,12 +75,45 @@ static void test_getttyname_malloc(void) {
assert_se(PATH_IN_SET(ttyname, "ptmx", "pts/ptmx"));
}
+static void test_one_color(const char *name, const char *color) {
+ printf("<%s%s%s>\n", color, name, ansi_normal());
+}
+
+static void test_colors(void) {
+ log_info("/* %s */", __func__);
+
+ test_one_color("normal", ansi_normal());
+ test_one_color("highlight", ansi_highlight());
+ test_one_color("red", ansi_red());
+ test_one_color("green", ansi_green());
+ test_one_color("yellow", ansi_yellow());
+ test_one_color("blue", ansi_blue());
+ test_one_color("megenta", ansi_magenta());
+ test_one_color("grey", ansi_grey());
+ test_one_color("highlight-red", ansi_highlight_red());
+ test_one_color("highlight-green", ansi_highlight_green());
+ test_one_color("highlight-yellow", ansi_highlight_yellow());
+ test_one_color("highlight-blue", ansi_highlight_blue());
+ test_one_color("highlight-magenta", ansi_highlight_magenta());
+ test_one_color("highlight-grey", ansi_highlight_grey());
+
+ test_one_color("underline", ansi_underline());
+ test_one_color("highlight-underline", ansi_highlight_underline());
+ test_one_color("highlight-red-underline", ansi_highlight_red_underline());
+ test_one_color("highlight-green-underline", ansi_highlight_green_underline());
+ test_one_color("highlight-yellow-underline", ansi_highlight_yellow_underline());
+ test_one_color("highlight-blue-underline", ansi_highlight_blue_underline());
+ test_one_color("highlight-magenta-underline", ansi_highlight_magenta_underline());
+ test_one_color("highlight-grey-underline", ansi_highlight_grey_underline());
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_default_term_for_tty();
test_read_one_char();
test_getttyname_malloc();
+ test_colors();
return 0;
}
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index ab31f5a2f1..af43597596 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -22,7 +22,7 @@
#include "signal-util.h"
#include "string-util.h"
#include "tests.h"
-#include "udev.h"
+#include "udev-event.h"
static int fake_filesystems(void) {
static const struct fakefs {
diff --git a/src/test/test-umask-util.c b/src/test/test-umask-util.c
new file mode 100644
index 0000000000..27f6b56541
--- /dev/null
+++ b/src/test/test-umask-util.c
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "tests.h"
+#include "umask-util.h"
+
+int main(int argc, char *argv[]) {
+ size_t n;
+ mode_t u;
+
+ test_setup_logging(LOG_DEBUG);
+
+ u = umask(0111);
+
+ n = 0;
+ RUN_WITH_UMASK(0123) {
+ assert_se(umask(000) == 0123);
+ n++;
+ }
+
+ assert_se(n == 1);
+ assert_se(umask(u) == 0111);
+
+ RUN_WITH_UMASK(0135) {
+ assert_se(umask(000) == 0135);
+ n++;
+ }
+
+ assert_se(n == 2);
+ assert_se(umask(0111) == u);
+
+ RUN_WITH_UMASK(0315) {
+ assert_se(umask(000) == 0315);
+ n++;
+ break;
+ }
+
+ assert_se(n == 3);
+ assert_se(umask(u) == 0111);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 8a0251e13a..8bc5bf6038 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -1,931 +1,85 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <unistd.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 "format-util.h"
-#include "fs-util.h"
-#include "hashmap.h"
-#include "hostname-util.h"
-#include "install-printf.h"
-#include "install.h"
-#include "load-fragment.h"
-#include "macro.h"
-#include "memory-util.h"
-#include "rm-rf.h"
-#include "specifier.h"
-#include "string-util.h"
+#include "path-lookup.h"
+#include "set.h"
#include "strv.h"
-#include "test-helper.h"
#include "tests.h"
-#include "tmpfile-util.h"
-#include "user-util.h"
-
-static int test_unit_file_get_set(void) {
- int r;
- Hashmap *h;
+#include "unit-file.h"
+
+static void test_unit_validate_alias_symlink_and_warn(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.service") == 0);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.socket") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.foobar") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.service") == 0);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.socket") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@YYY.service") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@XXX.service") == 0);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@.service") == 0);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b.service") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b@.service") == -EXDEV);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a@.slice", "/other/b.slice") == -EINVAL);
+ assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL);
+}
+
+static void test_unit_file_build_name_map(char **ids) {
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
+ _cleanup_hashmap_free_ Hashmap *unit_ids = NULL;
+ _cleanup_hashmap_free_ Hashmap *unit_names = NULL;
Iterator i;
- UnitFileList *p;
-
- h = hashmap_new(&string_hash_ops);
- assert_se(h);
-
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
- 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");
- if (r < 0)
- return EXIT_FAILURE;
-
- HASHMAP_FOREACH(p, h, i)
- printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
-
- unit_file_list_free(h);
-
- return 0;
-}
-
-static void check_execcommand(ExecCommand *c,
- const char* path,
- const char* argv0,
- const char* argv1,
- const char* argv2,
- bool ignore) {
- size_t n;
-
- assert_se(c);
- log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
- path, argv0 ?: path, argv1, argv2);
- n = strv_length(c->argv);
- log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
- c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
- assert_se(streq(c->path, path));
- assert_se(streq(c->argv[0], argv0 ?: path));
- if (n > 0)
- assert_se(streq_ptr(c->argv[1], argv1));
- if (n > 1)
- assert_se(streq_ptr(c->argv[2], argv2));
- assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
-}
-
-static void test_config_parse_exec(void) {
- /* int config_parse_exec(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) */
+ const char *k, *dst;
+ char **v;
+ usec_t mtime = 0;
int r;
- ExecCommand *c = NULL, *c1;
- const char *ccc;
- _cleanup_(manager_freep) Manager *m = NULL;
- _cleanup_(unit_freep) Unit *u = NULL;
-
- 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;
- }
-
- assert_se(r >= 0);
- assert_se(manager_startup(m, NULL, NULL) >= 0);
-
- assert_se(u = unit_new(m, sizeof(Service)));
-
- log_info("/* basic test */");
- r = config_parse_exec(NULL, "fake", 1, "section", 1,
- "LValue", 0, "/RValue r1",
- &c, u);
- assert_se(r >= 0);
- check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
-
- r = config_parse_exec(NULL, "fake", 2, "section", 1,
- "LValue", 0, "/RValue///slashes r1///",
- &c, u);
-
- log_info("/* test slashes */");
- assert_se(r >= 0);
- c1 = c->command_next;
- check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
-
- log_info("/* trailing slash */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "/RValue/ argv0 r1",
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
-
- log_info("/* honour_argv0 */");
- r = config_parse_exec(NULL, "fake", 3, "section", 1,
- "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
-
- log_info("/* honour_argv0, no args */");
- r = config_parse_exec(NULL, "fake", 3, "section", 1,
- "LValue", 0, "@/RValue",
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
-
- log_info("/* no command, whitespace only, reset */");
- r = config_parse_exec(NULL, "fake", 3, "section", 1,
- "LValue", 0, " ",
- &c, u);
- assert_se(r == 0);
- assert_se(c == NULL);
-
- log_info("/* ignore && honour_argv0 */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "-@/RValue///slashes3 argv0a r1",
- &c, u);
- assert_se(r >= 0);
- c1 = c;
- check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
-
- log_info("/* ignore && honour_argv0 */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "@-/RValue///slashes4 argv0b r1",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
-
- log_info("/* ignore && ignore */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "--/RValue argv0 r1",
- &c, u);
- assert_se(r == 0);
- assert_se(c1->command_next == NULL);
-
- log_info("/* ignore && ignore (2) */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "-@-/RValue argv0 r1",
- &c, u);
- assert_se(r == 0);
- assert_se(c1->command_next == NULL);
-
- log_info("/* semicolon */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "-@/RValue argv0 r1 ; "
- "/goo/goo boo",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
-
- c1 = c1->command_next;
- check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
-
- log_info("/* two semicolons in a row */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "-@/RValue argv0 r1 ; ; "
- "/goo/goo boo",
- &c, u);
- assert_se(r == -ENOEXEC);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
-
- /* second command fails because the executable name is ";" */
- assert_se(c1->command_next == NULL);
-
- log_info("/* trailing semicolon */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "-@/RValue argv0 r1 ; ",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
-
- assert_se(c1->command_next == NULL);
-
- log_info("/* trailing semicolon, no whitespace */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "-@/RValue argv0 r1 ;",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
-
- assert_se(c1->command_next == NULL);
-
- log_info("/* trailing semicolon in single quotes */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "-@/RValue argv0 r1 ';'",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
-
- log_info("/* escaped semicolon */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/bin/find \\;",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
-
- log_info("/* escaped semicolon with following arg */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/sbin/find \\; /x",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/sbin/find", NULL, ";", "/x", false);
-
- log_info("/* escaped semicolon as part of an expression */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/sbin/find \\;x",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/sbin/find", NULL, "\\;x", NULL, false);
+ assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0);
- log_info("/* encoded semicolon */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/bin/find \\073",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+ assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1);
- log_info("/* quoted semicolon */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/bin/find \";\"",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
+ HASHMAP_FOREACH_KEY(dst, k, unit_ids, i)
+ log_info("ids: %s → %s", k, dst);
- log_info("/* quoted semicolon with following arg */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/sbin/find \";\" /x",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/sbin/find", NULL, ";", "/x", false);
-
- log_info("/* spaces in the filename */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "\"/PATH WITH SPACES/daemon\" -1 -2",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
-
- log_info("/* spaces in the filename, no args */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "\"/PATH WITH SPACES/daemon -1 -2\"",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
-
- log_info("/* spaces in the filename, everything quoted */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
-
- log_info("/* escaped spaces in the filename */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
-
- log_info("/* escaped spaces in the filename (2) */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1,
- "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
-
- for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
- /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
- char path[] = "/path\\X";
- path[sizeof(path) - 2] = *ccc;
-
- log_info("/* invalid character: \\%c */", *ccc);
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, path,
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
+ HASHMAP_FOREACH_KEY(v, k, unit_names, i) {
+ _cleanup_free_ char *j = strv_join(v, ", ");
+ log_info("aliases: %s ← %s", k, j);
}
- log_info("/* valid character: \\s */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "/path\\s",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
-
- log_info("/* quoted backslashes */");
- r = config_parse_exec(NULL, "fake", 5, "section", 1,
- "LValue", 0,
- "/bin/grep '\\w+\\K'",
- &c, u);
- assert_se(r >= 0);
- c1 = c1->command_next;
- check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
-
- log_info("/* trailing backslash: \\ */");
- /* backslash is invalid */
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "/path\\",
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
-
- log_info("/* missing ending ' */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "/path 'foo",
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
-
- log_info("/* missing ending ' with trailing backslash */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "/path 'foo\\",
- &c, u);
- assert_se(r == -ENOEXEC);
- assert_se(c1->command_next == NULL);
-
- log_info("/* invalid space between modifiers */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "- /path",
- &c, u);
- assert_se(r == 0);
- assert_se(c1->command_next == NULL);
-
- log_info("/* only modifiers, no path */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "-",
- &c, u);
- assert_se(r == 0);
- assert_se(c1->command_next == NULL);
-
- log_info("/* empty argument, reset */");
- r = config_parse_exec(NULL, "fake", 4, "section", 1,
- "LValue", 0, "",
- &c, u);
- assert_se(r == 0);
- assert_se(c == NULL);
-
- exec_command_free_list(c);
-}
-
-static void test_config_parse_log_extra_fields(void) {
- /* int config_parse_log_extra_fields(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) */
-
- int r;
-
- _cleanup_(manager_freep) Manager *m = NULL;
- _cleanup_(unit_freep) Unit *u = NULL;
- ExecContext c = {};
-
- 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;
+ char buf[FORMAT_TIMESTAMP_MAX];
+ log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime));
+
+ r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL);
+ assert_se(IN_SET(r, 0, 1));
+ if (r == 0)
+ log_debug("Cache rebuild skipped based on mtime.");
+
+
+ char **id;
+ STRV_FOREACH(id, ids) {
+ const char *fragment, *name;
+ Iterator it;
+ _cleanup_set_free_free_ Set *names = NULL;
+ log_info("*** %s ***", *id);
+ r = unit_file_find_fragment(unit_ids,
+ unit_names,
+ *id,
+ &fragment,
+ &names);
+ assert(r == 0);
+ log_info("fragment: %s", fragment);
+ log_info("names:");
+ SET_FOREACH(name, names, it)
+ log_info(" %s", name);
}
-
- assert_se(r >= 0);
- assert_se(manager_startup(m, NULL, NULL) >= 0);
-
- assert_se(u = unit_new(m, sizeof(Service)));
-
- log_info("/* %s – basic test */", __func__);
- r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
- "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
- &c, u);
- assert_se(r >= 0);
- assert_se(c.n_log_extra_fields == 2);
- assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
- assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
-
- log_info("/* %s – add some */", __func__);
- r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
- "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
- &c, u);
- assert_se(r >= 0);
- assert_se(c.n_log_extra_fields == 4);
- assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
- assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
- assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
- assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
-
- exec_context_dump(&c, stdout, " --> ");
-
- log_info("/* %s – reset */", __func__);
- r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
- "LValue", 0, "",
- &c, u);
- assert_se(r >= 0);
- assert_se(c.n_log_extra_fields == 0);
-
- exec_context_free_log_extra_fields(&c);
-
- log_info("/* %s – bye */", __func__);
}
-#define env_file_1 \
- "a=a\n" \
- "b=b\\\n" \
- "c\n" \
- "d=d\\\n" \
- "e\\\n" \
- "f\n" \
- "g=g\\ \n" \
- "h=h\n" \
- "i=i\\"
-
-#define env_file_2 \
- "a=a\\\n"
-
-#define env_file_3 \
- "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
- "#--nouser-config \\\n" \
- "normal=line"
-
-#define env_file_4 \
- "# Generated\n" \
- "\n" \
- "HWMON_MODULES=\"coretemp f71882fg\"\n" \
- "\n" \
- "# For compatibility reasons\n" \
- "\n" \
- "MODULE_0=coretemp\n" \
- "MODULE_1=f71882fg"
-
-#define env_file_5 \
- "a=\n" \
- "b="
-
-static void test_load_env_file_1(void) {
- _cleanup_strv_free_ char **data = NULL;
- int r;
-
- _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
- _cleanup_close_ int fd;
-
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1));
-
- 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"));
- assert_se(streq(data[2], "d=def"));
- assert_se(streq(data[3], "g=g "));
- assert_se(streq(data[4], "h=h"));
- assert_se(streq(data[5], "i=i"));
- assert_se(data[6] == NULL);
-}
-
-static void test_load_env_file_2(void) {
- _cleanup_strv_free_ char **data = NULL;
- int r;
-
- _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
- _cleanup_close_ int fd;
+int main(int argc, char **argv) {
+ test_setup_logging(LOG_DEBUG);
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2));
+ test_unit_validate_alias_symlink_and_warn();
+ test_unit_file_build_name_map(strv_skip(argv, 1));
- r = load_env_file(NULL, name, &data);
- assert_se(r == 0);
- assert_se(streq(data[0], "a=a"));
- assert_se(data[1] == NULL);
-}
-
-static void test_load_env_file_3(void) {
- _cleanup_strv_free_ char **data = NULL;
- int r;
-
- _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
- _cleanup_close_ int fd;
-
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3));
-
- r = load_env_file(NULL, name, &data);
- assert_se(r == 0);
- assert_se(data == NULL);
-}
-
-static void test_load_env_file_4(void) {
- _cleanup_strv_free_ char **data = NULL;
- _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
- _cleanup_close_ int fd;
- int r;
-
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4));
-
- 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"));
- assert_se(streq(data[2], "MODULE_1=f71882fg"));
- assert_se(data[3] == NULL);
-}
-
-static void test_load_env_file_5(void) {
- _cleanup_strv_free_ char **data = NULL;
- int r;
-
- _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
- _cleanup_close_ int fd;
-
- fd = mkostemp_safe(name);
- assert_se(fd >= 0);
- assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5));
-
- r = load_env_file(NULL, name, &data);
- assert_se(r == 0);
- assert_se(streq(data[0], "a="));
- assert_se(streq(data[1], "b="));
- assert_se(data[2] == NULL);
-}
-
-static void test_install_printf(void) {
- char name[] = "name.service",
- path[] = "/run/systemd/system/name.service";
- UnitFileInstallInfo i = { .name = name, .path = path, };
- UnitFileInstallInfo i2 = { .name= name, .path = path, };
- char name3[] = "name@inst.service",
- path3[] = "/run/systemd/system/name.service";
- UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
- UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
-
- _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);
-
-#define expect(src, pattern, result) \
- do { \
- _cleanup_free_ char *t = NULL; \
- _cleanup_free_ char \
- *d1 = strdup(i.name), \
- *d2 = strdup(i.path); \
- assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
- memzero(i.name, strlen(i.name)); \
- memzero(i.path, strlen(i.path)); \
- assert_se(d1 && d2); \
- if (result) { \
- printf("%s\n", t); \
- assert_se(streq(t, result)); \
- } else assert_se(t == NULL); \
- strcpy(i.name, d1); \
- strcpy(i.path, d2); \
- } while (false)
-
- expect(i, "%n", "name.service");
- expect(i, "%N", "name");
- 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);
-
- expect(i, "%m", mid);
- 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);
-
- expect(i3, "%m", mid);
- expect(i3, "%b", bid);
- expect(i3, "%H", host);
-
- expect(i4, "%g", group);
- expect(i4, "%G", gid);
- expect(i4, "%u", user);
- expect(i4, "%U", uid);
-}
-
-static uint64_t make_cap(int cap) {
- return ((uint64_t) 1ULL << (uint64_t) cap);
-}
-
-static void test_config_parse_capability_set(void) {
- /* int config_parse_capability_set(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) */
- int r;
- uint64_t capability_bounding_set = 0;
-
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, "CAP_NET_RAW",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
-
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
-
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
-
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, "",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(capability_bounding_set == UINT64_C(0));
-
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, "~",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(cap_test_all(capability_bounding_set));
-
- capability_bounding_set = 0;
- r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
- "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
- &capability_bounding_set, NULL);
- assert_se(r >= 0);
- assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
-}
-
-static void test_config_parse_rlimit(void) {
- struct rlimit * rl[_RLIMIT_MAX] = {};
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
- assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
-
- rl[RLIMIT_NOFILE]->rlim_cur = 10;
- rl[RLIMIT_NOFILE]->rlim_max = 20;
-
- /* Invalid values don't change rl */
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
- assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
- assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
- assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_NOFILE]);
- assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
- assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
-
- rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_CPU]);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_CPU]);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_CPU]);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
- assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_CPU]);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_CPU]);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
- assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
-
- rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
- assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
- assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
-
- assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
- assert_se(rl[RLIMIT_RTTIME]);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
- assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
-
- rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
-}
-
-static void test_config_parse_pass_environ(void) {
- /* int config_parse_pass_environ(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) */
- int r;
- _cleanup_strv_free_ char **passenv = NULL;
-
- r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "A B",
- &passenv, NULL);
- assert_se(r >= 0);
- assert_se(strv_length(passenv) == 2);
- assert_se(streq(passenv[0], "A"));
- assert_se(streq(passenv[1], "B"));
-
- r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "",
- &passenv, NULL);
- assert_se(r >= 0);
- assert_se(strv_isempty(passenv));
-
- r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
- &passenv, NULL);
- assert_se(r >= 0);
- assert_se(strv_length(passenv) == 1);
- assert_se(streq(passenv[0], "normal_name"));
-
-}
-
-static void test_unit_dump_config_items(void) {
- unit_dump_config_items(stdout);
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
- int r;
-
- test_setup_logging(LOG_INFO);
-
- r = enter_cgroup_subroot();
- if (r == -ENOMEDIUM)
- return log_tests_skipped("cgroupfs not available");
-
- assert_se(runtime_dir = setup_fake_runtime_dir());
-
- r = test_unit_file_get_set();
- test_config_parse_exec();
- test_config_parse_log_extra_fields();
- test_config_parse_capability_set();
- test_config_parse_rlimit();
- test_config_parse_pass_environ();
- test_load_env_file_1();
- test_load_env_file_2();
- test_load_env_file_3();
- test_load_env_file_4();
- test_load_env_file_5();
- TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
- test_unit_dump_config_items();
-
- return r;
+ return 0;
}
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 8b230bb290..4d1e49b675 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -50,6 +50,9 @@ static void test_unit_name_is_valid(void) {
assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE));
assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE));
assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid(".test.service", UNIT_NAME_PLAIN));
+ assert_se( unit_name_is_valid(".test@.service", UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("_strange::::.service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("", UNIT_NAME_ANY));
@@ -430,29 +433,31 @@ static void test_unit_name_to_instance(void) {
int r;
r = unit_name_to_instance("foo@bar.service", &instance);
- assert_se(r >= 0);
+ assert_se(r == UNIT_NAME_INSTANCE);
assert_se(streq(instance, "bar"));
free(instance);
r = unit_name_to_instance("foo@.service", &instance);
- assert_se(r >= 0);
+ assert_se(r == UNIT_NAME_TEMPLATE);
assert_se(streq(instance, ""));
free(instance);
r = unit_name_to_instance("fo0-stUff_b@b.service", &instance);
- assert_se(r >= 0);
+ assert_se(r == UNIT_NAME_INSTANCE);
assert_se(streq(instance, "b"));
free(instance);
r = unit_name_to_instance("foo.service", &instance);
- assert_se(r == 0);
+ assert_se(r == UNIT_NAME_PLAIN);
assert_se(!instance);
r = unit_name_to_instance("fooj@unk", &instance);
assert_se(r < 0);
+ assert_se(!instance);
r = unit_name_to_instance("foo@", &instance);
assert_se(r < 0);
+ assert_se(!instance);
}
static void test_unit_name_escape(void) {
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 1a507bc00a..9475b99c28 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -61,6 +61,43 @@ static void test_uid_ptr(void) {
assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
}
+static void test_valid_user_group_name_compat(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(!valid_user_group_name_compat(NULL));
+ assert_se(!valid_user_group_name_compat(""));
+ assert_se(!valid_user_group_name_compat("1"));
+ assert_se(!valid_user_group_name_compat("65535"));
+ assert_se(!valid_user_group_name_compat("-1"));
+ assert_se(!valid_user_group_name_compat("-kkk"));
+ assert_se(!valid_user_group_name_compat("rööt"));
+ assert_se(!valid_user_group_name_compat("."));
+ assert_se(!valid_user_group_name_compat(".eff"));
+ assert_se(!valid_user_group_name_compat("foo\nbar"));
+ assert_se(!valid_user_group_name_compat("0123456789012345678901234567890123456789"));
+ assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
+ assert_se(!valid_user_group_name_compat("."));
+ assert_se(!valid_user_group_name_compat(".1"));
+ assert_se(!valid_user_group_name_compat(".65535"));
+ assert_se(!valid_user_group_name_compat(".-1"));
+ assert_se(!valid_user_group_name_compat(".-kkk"));
+ assert_se(!valid_user_group_name_compat(".rööt"));
+ assert_se(!valid_user_group_name_or_id_compat(".aaa:bbb"));
+
+ assert_se(valid_user_group_name_compat("root"));
+ assert_se(valid_user_group_name_compat("lennart"));
+ assert_se(valid_user_group_name_compat("LENNART"));
+ assert_se(valid_user_group_name_compat("_kkk"));
+ assert_se(valid_user_group_name_compat("kkk-"));
+ assert_se(valid_user_group_name_compat("kk-k"));
+ assert_se(valid_user_group_name_compat("eff.eff"));
+ assert_se(valid_user_group_name_compat("eff."));
+
+ assert_se(valid_user_group_name_compat("some5"));
+ assert_se(!valid_user_group_name_compat("5some"));
+ assert_se(valid_user_group_name_compat("INNER5NUMBER"));
+}
+
static void test_valid_user_group_name(void) {
log_info("/* %s */", __func__);
@@ -72,10 +109,17 @@ static void test_valid_user_group_name(void) {
assert_se(!valid_user_group_name("-kkk"));
assert_se(!valid_user_group_name("rööt"));
assert_se(!valid_user_group_name("."));
- assert_se(!valid_user_group_name("eff.eff"));
+ assert_se(!valid_user_group_name(".eff"));
assert_se(!valid_user_group_name("foo\nbar"));
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789"));
assert_se(!valid_user_group_name_or_id("aaa:bbb"));
+ assert_se(!valid_user_group_name("."));
+ assert_se(!valid_user_group_name(".1"));
+ assert_se(!valid_user_group_name(".65535"));
+ assert_se(!valid_user_group_name(".-1"));
+ assert_se(!valid_user_group_name(".-kkk"));
+ assert_se(!valid_user_group_name(".rööt"));
+ assert_se(!valid_user_group_name_or_id(".aaa:bbb"));
assert_se(valid_user_group_name("root"));
assert_se(valid_user_group_name("lennart"));
@@ -83,12 +127,47 @@ static void test_valid_user_group_name(void) {
assert_se(valid_user_group_name("_kkk"));
assert_se(valid_user_group_name("kkk-"));
assert_se(valid_user_group_name("kk-k"));
+ assert_se(!valid_user_group_name("eff.eff"));
+ assert_se(!valid_user_group_name("eff."));
assert_se(valid_user_group_name("some5"));
assert_se(!valid_user_group_name("5some"));
assert_se(valid_user_group_name("INNER5NUMBER"));
}
+static void test_valid_user_group_name_or_id_compat(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(!valid_user_group_name_or_id_compat(NULL));
+ assert_se(!valid_user_group_name_or_id_compat(""));
+ assert_se(valid_user_group_name_or_id_compat("0"));
+ assert_se(valid_user_group_name_or_id_compat("1"));
+ assert_se(valid_user_group_name_or_id_compat("65534"));
+ assert_se(!valid_user_group_name_or_id_compat("65535"));
+ assert_se(valid_user_group_name_or_id_compat("65536"));
+ assert_se(!valid_user_group_name_or_id_compat("-1"));
+ assert_se(!valid_user_group_name_or_id_compat("-kkk"));
+ assert_se(!valid_user_group_name_or_id_compat("rööt"));
+ assert_se(!valid_user_group_name_or_id_compat("."));
+ assert_se(!valid_user_group_name_or_id_compat(".eff"));
+ assert_se(valid_user_group_name_or_id_compat("eff.eff"));
+ assert_se(valid_user_group_name_or_id_compat("eff."));
+ assert_se(!valid_user_group_name_or_id_compat("foo\nbar"));
+ assert_se(!valid_user_group_name_or_id_compat("0123456789012345678901234567890123456789"));
+ assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
+
+ assert_se(valid_user_group_name_or_id_compat("root"));
+ assert_se(valid_user_group_name_or_id_compat("lennart"));
+ assert_se(valid_user_group_name_or_id_compat("LENNART"));
+ assert_se(valid_user_group_name_or_id_compat("_kkk"));
+ assert_se(valid_user_group_name_or_id_compat("kkk-"));
+ assert_se(valid_user_group_name_or_id_compat("kk-k"));
+
+ assert_se(valid_user_group_name_or_id_compat("some5"));
+ assert_se(!valid_user_group_name_or_id_compat("5some"));
+ assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER"));
+}
+
static void test_valid_user_group_name_or_id(void) {
log_info("/* %s */", __func__);
@@ -103,7 +182,9 @@ static void test_valid_user_group_name_or_id(void) {
assert_se(!valid_user_group_name_or_id("-kkk"));
assert_se(!valid_user_group_name_or_id("rööt"));
assert_se(!valid_user_group_name_or_id("."));
+ assert_se(!valid_user_group_name_or_id(".eff"));
assert_se(!valid_user_group_name_or_id("eff.eff"));
+ assert_se(!valid_user_group_name_or_id("eff."));
assert_se(!valid_user_group_name_or_id("foo\nbar"));
assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789"));
assert_se(!valid_user_group_name_or_id("aaa:bbb"));
@@ -191,6 +272,20 @@ static void test_get_group_creds_one(const char *id, const char *name, gid_t gid
assert_se(rgid == gid);
}
+static void test_make_salt(void) {
+ log_info("/* %s */", __func__);
+
+ _cleanup_free_ char *s, *t;
+
+ assert_se(make_salt(&s) == 0);
+ log_info("got %s", s);
+
+ assert_se(make_salt(&t) == 0);
+ log_info("got %s", t);
+
+ assert(!streq(s, t));
+}
+
int main(int argc, char *argv[]) {
test_uid_to_name_one(0, "root");
test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
@@ -205,8 +300,8 @@ int main(int argc, char *argv[]) {
test_get_user_creds_one("root", "root", 0, 0, "/root", "/bin/sh");
test_get_user_creds_one("0", "root", 0, 0, "/root", "/bin/sh");
- test_get_user_creds_one(NOBODY_USER_NAME, NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin");
- test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin");
+ test_get_user_creds_one(NOBODY_USER_NAME, NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", NOLOGIN);
+ test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", NOLOGIN);
test_get_group_creds_one("root", "root", 0);
test_get_group_creds_one("0", "root", 0);
@@ -216,10 +311,14 @@ int main(int argc, char *argv[]) {
test_parse_uid();
test_uid_ptr();
+ test_valid_user_group_name_compat();
test_valid_user_group_name();
+ test_valid_user_group_name_or_id_compat();
test_valid_user_group_name_or_id();
test_valid_gecos();
test_valid_home();
+ test_make_salt();
+
return 0;
}
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index d1e48da2a6..b5c4e3dc34 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -7,6 +7,8 @@
#include "util.h"
static void test_utf8_is_printable(void) {
+ log_info("/* %s */", __func__);
+
assert_se(utf8_is_printable("ascii is valid\tunicode", 22));
assert_se(utf8_is_printable("\342\204\242", 3));
assert_se(!utf8_is_printable("\341\204", 2));
@@ -14,18 +16,24 @@ static void test_utf8_is_printable(void) {
}
static void test_utf8_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(utf8_is_valid("ascii is valid unicode"));
assert_se(utf8_is_valid("\342\204\242"));
assert_se(!utf8_is_valid("\341\204"));
}
static void test_ascii_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se( ascii_is_valid("alsdjf\t\vbarr\nba z"));
assert_se(!ascii_is_valid("\342\204\242"));
assert_se(!ascii_is_valid("\341\204"));
}
static void test_ascii_is_valid_n(void) {
+ log_info("/* %s */", __func__);
+
assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 17));
assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 16));
assert_se(!ascii_is_valid_n("alsdjf\t\vbarr\nba z", 18));
@@ -36,6 +44,8 @@ static void test_ascii_is_valid_n(void) {
}
static void test_utf8_encoded_valid_unichar(void) {
+ log_info("/* %s */", __func__);
+
assert_se(utf8_encoded_valid_unichar("\342\204\242", 1) == -EINVAL); /* truncated */
assert_se(utf8_encoded_valid_unichar("\342\204\242", 2) == -EINVAL); /* truncated */
assert_se(utf8_encoded_valid_unichar("\342\204\242", 3) == 3);
@@ -53,9 +63,11 @@ static void test_utf8_encoded_valid_unichar(void) {
assert_se(utf8_encoded_valid_unichar("\341\204\341\204", 5) == -EINVAL);
}
-static void test_utf8_escaping(void) {
+static void test_utf8_escape_invalid(void) {
_cleanup_free_ char *p1, *p2, *p3;
+ log_info("/* %s */", __func__);
+
p1 = utf8_escape_invalid("goo goo goo");
puts(p1);
assert_se(utf8_is_valid(p1));
@@ -69,9 +81,11 @@ static void test_utf8_escaping(void) {
assert_se(utf8_is_valid(p3));
}
-static void test_utf8_escaping_printable(void) {
+static void test_utf8_escape_non_printable(void) {
_cleanup_free_ char *p1, *p2, *p3, *p4, *p5, *p6;
+ log_info("/* %s */", __func__);
+
p1 = utf8_escape_non_printable("goo goo goo");
puts(p1);
assert_se(utf8_is_valid(p1));
@@ -97,12 +111,45 @@ static void test_utf8_escaping_printable(void) {
assert_se(utf8_is_valid(p6));
}
+static void test_utf8_escape_non_printable_full(void) {
+ log_info("/* %s */", __func__);
+
+ for (size_t i = 0; i < 20; i++) {
+ _cleanup_free_ char *p;
+
+ p = utf8_escape_non_printable_full("goo goo goo", i);
+ puts(p);
+ assert_se(utf8_is_valid(p));
+ assert_se(utf8_console_width(p) <= i);
+ }
+
+ for (size_t i = 0; i < 20; i++) {
+ _cleanup_free_ char *p;
+
+ p = utf8_escape_non_printable_full("\001 \019\20\a", i);
+ puts(p);
+ assert_se(utf8_is_valid(p));
+ assert_se(utf8_console_width(p) <= i);
+ }
+
+ for (size_t i = 0; i < 20; i++) {
+ _cleanup_free_ char *p;
+
+ p = utf8_escape_non_printable_full("\xef\xbf\x30\x13", i);
+ puts(p);
+ assert_se(utf8_is_valid(p));
+ assert_se(utf8_console_width(p) <= i);
+ }
+}
+
static void test_utf16_to_utf8(void) {
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;
+ log_info("/* %s */", __func__);
+
/* Convert UTF-16 to UTF-8, filtering embedded bad chars */
a = utf16_to_utf8(utf16, sizeof(utf16));
assert_se(a);
@@ -120,6 +167,8 @@ static void test_utf16_to_utf8(void) {
}
static void test_utf8_n_codepoints(void) {
+ log_info("/* %s */", __func__);
+
assert_se(utf8_n_codepoints("abc") == 3);
assert_se(utf8_n_codepoints("zażółcić gęślą jaźń") == 19);
assert_se(utf8_n_codepoints("串") == 1);
@@ -129,6 +178,8 @@ static void test_utf8_n_codepoints(void) {
}
static void test_utf8_console_width(void) {
+ log_info("/* %s */", __func__);
+
assert_se(utf8_console_width("abc") == 3);
assert_se(utf8_console_width("zażółcić gęślą jaźń") == 19);
assert_se(utf8_console_width("串") == 2);
@@ -140,6 +191,8 @@ static void test_utf8_console_width(void) {
static void test_utf8_to_utf16(void) {
const char *p;
+ log_info("/* %s */", __func__);
+
FOREACH_STRING(p,
"abc",
"zażółcić gęślą jaźń",
@@ -165,8 +218,9 @@ int main(int argc, char *argv[]) {
test_ascii_is_valid();
test_ascii_is_valid_n();
test_utf8_encoded_valid_unichar();
- test_utf8_escaping();
- test_utf8_escaping_printable();
+ test_utf8_escape_invalid();
+ test_utf8_escape_non_printable();
+ test_utf8_escape_non_printable_full();
test_utf16_to_utf8();
test_utf8_n_codepoints();
test_utf8_console_width();
diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c
new file mode 100644
index 0000000000..fbfc72cd81
--- /dev/null
+++ b/src/test/test-varlink.c
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "sd-event.h"
+
+#include "fd-util.h"
+#include "json.h"
+#include "rm-rf.h"
+#include "strv.h"
+#include "tmpfile-util.h"
+#include "user-util.h"
+#include "varlink.h"
+
+/* Let's pick some high value, that is higher than the largest listen() backlog, but leaves enough room below
+ the typical RLIMIT_NOFILE value of 1024 so that we can process both sides of each socket in our
+ process. Or in other words: "OVERLOAD_CONNECTIONS * 2 + x < 1024" should hold, for some small x that
+ should cover any auxiliary fds, the listener server fds, stdin/stdout/stderr and whatever else. */
+#define OVERLOAD_CONNECTIONS 333
+
+static int n_done = 0;
+static int block_write_fd = -1;
+
+static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+ _cleanup_(json_variant_unrefp) JsonVariant *ret = NULL;
+ JsonVariant *a, *b;
+ intmax_t x, y;
+ int r;
+
+ a = json_variant_by_key(parameters, "a");
+ if (!a)
+ return varlink_error(link, "io.test.BadParameters", NULL);
+
+ x = json_variant_integer(a);
+
+ b = json_variant_by_key(parameters, "b");
+ if (!b)
+ return varlink_error(link, "io.test.BadParameters", NULL);
+
+ y = json_variant_integer(b);
+
+ r = json_build(&ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("sum", JSON_BUILD_INTEGER(x + y))));
+ if (r < 0)
+ return r;
+
+ return varlink_reply(link, ret);
+}
+
+static int method_done(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+
+ if (++n_done == 2)
+ sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+ return 0;
+}
+
+static int reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+ JsonVariant *sum;
+
+ sum = json_variant_by_key(parameters, "sum");
+
+ assert_se(json_variant_integer(sum) == 7+22);
+
+ if (++n_done == 2)
+ sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+ return 0;
+}
+
+static int on_connect(VarlinkServer *s, Varlink *link, void *userdata) {
+ uid_t uid = UID_INVALID;
+
+ assert(s);
+ assert(link);
+
+ assert_se(varlink_get_peer_uid(link, &uid) >= 0);
+ assert_se(getuid() == uid);
+
+ return 0;
+}
+
+static int overload_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+
+ /* This method call reply should always be called with a disconnection, since the method call should
+ * be talking to an overloaded server */
+
+ log_debug("Over reply triggered with error: %s", strna(error_id));
+ assert_se(streq(error_id, VARLINK_ERROR_DISCONNECTED));
+ sd_event_exit(varlink_get_event(link), 0);
+
+ return 0;
+}
+
+static void flood_test(const char *address) {
+ _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+ _cleanup_free_ Varlink **connections = NULL;
+ size_t k;
+ char x = 'x';
+
+ log_debug("Flooding server...");
+
+ /* Block the main event loop while we flood */
+ assert_se(write(block_write_fd, &x, sizeof(x)) == sizeof(x));
+
+ assert_se(sd_event_default(&e) >= 0);
+
+ /* Flood the server with connections */
+ assert_se(connections = new0(Varlink*, OVERLOAD_CONNECTIONS));
+ for (k = 0; k < OVERLOAD_CONNECTIONS; k++) {
+ _cleanup_free_ char *t = NULL;
+ log_debug("connection %zu", k);
+ assert_se(varlink_connect_address(connections + k, address) >= 0);
+
+ assert_se(asprintf(&t, "flood-%zu", k) >= 0);
+ assert_se(varlink_set_description(connections[k], t) >= 0);
+ assert_se(varlink_attach_event(connections[k], e, k) >= 0);
+ assert_se(varlink_sendb(connections[k], "io.test.Rubbish", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("id", JSON_BUILD_INTEGER(k)))) >= 0);
+ }
+
+ /* Then, create one more, which should fail */
+ log_debug("Creating overload connection...");
+ assert_se(varlink_connect_address(&c, address) >= 0);
+ assert_se(varlink_set_description(c, "overload-client") >= 0);
+ assert_se(varlink_attach_event(c, e, k) >= 0);
+ assert_se(varlink_bind_reply(c, overload_reply) >= 0);
+ assert_se(varlink_invokeb(c, "io.test.Overload", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("foo", JSON_BUILD_STRING("bar")))) >= 0);
+
+ /* Unblock it */
+ log_debug("Unblocking server...");
+ block_write_fd = safe_close(block_write_fd);
+
+ /* This loop will terminate as soon as the overload reply callback is called */
+ assert_se(sd_event_loop(e) >= 0);
+
+ /* And close all connections again */
+ for (k = 0; k < OVERLOAD_CONNECTIONS; k++)
+ connections[k] = varlink_unref(connections[k]);
+}
+
+static void *thread(void *arg) {
+ _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+ _cleanup_(json_variant_unrefp) JsonVariant *i = NULL;
+ JsonVariant *o = NULL;
+ const char *e;
+
+ assert_se(json_build(&i, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(88)),
+ JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(99)))) >= 0);
+
+ assert_se(varlink_connect_address(&c, arg) >= 0);
+ assert_se(varlink_set_description(c, "thread-client") >= 0);
+
+ assert_se(varlink_call(c, "io.test.DoSomething", i, &o, &e, NULL) >= 0);
+ assert_se(json_variant_integer(json_variant_by_key(o, "sum")) == 88 + 99);
+ assert_se(!e);
+
+ assert_se(varlink_callb(c, "io.test.IDontExist", &o, &e, NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_REAL(5.5)))) >= 0);
+ assert_se(streq_ptr(json_variant_string(json_variant_by_key(o, "method")), "io.test.IDontExist"));
+ assert_se(streq(e, VARLINK_ERROR_METHOD_NOT_FOUND));
+
+ flood_test(arg);
+
+ assert_se(varlink_send(c, "io.test.Done", NULL) >= 0);
+
+ return NULL;
+}
+
+static int block_fd_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ char c;
+
+ assert_se(fd_nonblock(fd, false) >= 0);
+
+ assert_se(read(fd, &c, sizeof(c)) == sizeof(c));
+ /* When a character is written to this pipe we'll block until the pipe is closed. */
+
+ assert_se(read(fd, &c, sizeof(c)) == 0);
+
+ assert_se(fd_nonblock(fd, true) >= 0);
+
+ assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *block_event = NULL;
+ _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+ _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+ _cleanup_(close_pairp) int block_fds[2] = { -1, -1 };
+ pthread_t t;
+ const char *sp;
+
+ log_set_max_level(LOG_DEBUG);
+ log_open();
+
+ assert_se(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir) >= 0);
+ sp = strjoina(tmpdir, "/socket");
+
+ assert_se(sd_event_default(&e) >= 0);
+
+ assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0);
+ assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0);
+ assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0);
+ block_write_fd = TAKE_FD(block_fds[1]);
+
+ assert_se(varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID) >= 0);
+ assert_se(varlink_server_set_description(s, "our-server") >= 0);
+
+ assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
+ assert_se(varlink_server_bind_method(s, "io.test.Done", method_done) >= 0);
+ assert_se(varlink_server_bind_connect(s, on_connect) >= 0);
+ assert_se(varlink_server_listen_address(s, sp, 0600) >= 0);
+ assert_se(varlink_server_attach_event(s, e, 0) >= 0);
+ assert_se(varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0);
+
+ assert_se(varlink_connect_address(&c, sp) >= 0);
+ assert_se(varlink_set_description(c, "main-client") >= 0);
+ assert_se(varlink_bind_reply(c, reply) >= 0);
+
+ assert_se(json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(7)),
+ JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(22)))) >= 0);
+
+ assert_se(varlink_invoke(c, "io.test.DoSomething", v) >= 0);
+
+ assert_se(varlink_attach_event(c, e, 0) >= 0);
+
+ assert_se(pthread_create(&t, NULL, thread, (void*) sp) == 0);
+
+ assert_se(sd_event_loop(e) >= 0);
+
+ assert_se(pthread_join(t, NULL) == 0);
+
+ return 0;
+}