1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
7 #include "stdio-util.h"
8 #include "string-util.h"
12 static void test_specifier_escape_one(const char *a
, const char *b
) {
13 _cleanup_free_
char *x
= NULL
;
15 x
= specifier_escape(a
);
16 assert_se(streq_ptr(x
, b
));
19 TEST(specifier_escape
) {
20 test_specifier_escape_one(NULL
, NULL
);
21 test_specifier_escape_one("", "");
22 test_specifier_escape_one("%", "%%");
23 test_specifier_escape_one("foo bar", "foo bar");
24 test_specifier_escape_one("foo%bar", "foo%%bar");
25 test_specifier_escape_one("%%%%%", "%%%%%%%%%%");
28 static void test_specifier_escape_strv_one(char **a
, char **b
) {
29 _cleanup_strv_free_
char **x
= NULL
;
31 assert_se(specifier_escape_strv(a
, &x
) >= 0);
32 assert_se(strv_equal(x
, b
));
35 TEST(specifier_escape_strv
) {
36 test_specifier_escape_strv_one(NULL
, NULL
);
37 test_specifier_escape_strv_one(STRV_MAKE(NULL
), STRV_MAKE(NULL
));
38 test_specifier_escape_strv_one(STRV_MAKE(""), STRV_MAKE(""));
39 test_specifier_escape_strv_one(STRV_MAKE("foo"), STRV_MAKE("foo"));
40 test_specifier_escape_strv_one(STRV_MAKE("%"), STRV_MAKE("%%"));
41 test_specifier_escape_strv_one(STRV_MAKE("foo", "%", "foo%", "%foo", "foo%foo", "quux", "%%%"),
42 STRV_MAKE("foo", "%%", "foo%%", "%%foo", "foo%%foo", "quux", "%%%%%%"));
45 /* Any specifier functions which don't need an argument. */
46 static const Specifier specifier_table
[] = {
47 COMMON_SYSTEM_SPECIFIERS
,
49 COMMON_CREDS_SPECIFIERS
,
50 { 'h', specifier_user_home
, NULL
},
52 COMMON_TMP_SPECIFIERS
,
56 TEST(specifier_printf
) {
57 static const Specifier table
[] = {
58 { 'X', specifier_string
, (char*) "AAAA" },
59 { 'Y', specifier_string
, (char*) "BBBB" },
60 { 'e', specifier_string
, NULL
},
61 COMMON_SYSTEM_SPECIFIERS
,
65 _cleanup_free_
char *w
= NULL
;
68 r
= specifier_printf("xxx a=%X b=%Y e=%e yyy", SIZE_MAX
, table
, NULL
, NULL
, &w
);
73 assert_se(streq(w
, "xxx a=AAAA b=BBBB e= yyy"));
76 r
= specifier_printf("machine=%m, boot=%b, host=%H, pretty=%R, version=%v, arch=%a, empty=%e", SIZE_MAX
, table
, NULL
, NULL
, &w
);
82 specifier_printf("os=%o, os-version=%w, build=%B, variant=%W, empty=%e%e%e", SIZE_MAX
, table
, NULL
, NULL
, &w
);
87 TEST(specifier_real_path
) {
88 static const Specifier table
[] = {
89 { 'p', specifier_string
, "/dev/initctl" },
90 { 'y', specifier_real_path
, "/dev/initctl" },
91 { 'Y', specifier_real_directory
, "/dev/initctl" },
92 { 'w', specifier_real_path
, "/dev/tty" },
93 { 'W', specifier_real_directory
, "/dev/tty" },
97 _cleanup_free_
char *w
= NULL
;
100 r
= specifier_printf("p=%p y=%y Y=%Y w=%w W=%W", SIZE_MAX
, table
, NULL
, NULL
, &w
);
101 assert_se(r
>= 0 || r
== -ENOENT
);
102 assert_se(w
|| r
== -ENOENT
);
105 /* /dev/initctl should normally be a symlink to /run/initctl */
106 if (files_same("/dev/initctl", "/run/initctl", 0) > 0)
107 assert_se(streq(w
, "p=/dev/initctl y=/run/initctl Y=/run w=/dev/tty W=/dev"));
110 TEST(specifier_real_path_missing_file
) {
111 static const Specifier table
[] = {
112 { 'p', specifier_string
, "/dev/-no-such-file--" },
113 { 'y', specifier_real_path
, "/dev/-no-such-file--" },
114 { 'Y', specifier_real_directory
, "/dev/-no-such-file--" },
118 _cleanup_free_
char *w
= NULL
;
121 r
= specifier_printf("p=%p y=%y", SIZE_MAX
, table
, NULL
, NULL
, &w
);
122 assert_se(r
== -ENOENT
);
124 r
= specifier_printf("p=%p Y=%Y", SIZE_MAX
, table
, NULL
, NULL
, &w
);
125 assert_se(r
== -ENOENT
);
129 for (const Specifier
*s
= specifier_table
; s
->specifier
; s
++) {
131 _cleanup_free_
char *resolved
= NULL
;
133 xsprintf(spec
, "%%%c", s
->specifier
);
135 assert_se(specifier_printf(spec
, SIZE_MAX
, specifier_table
, NULL
, NULL
, &resolved
) >= 0);
137 log_info("%%%c → %s", s
->specifier
, resolved
);
141 DEFINE_TEST_MAIN(LOG_DEBUG
);