13 #include <logconfig.h>
15 static void conf_hash(const char *key, const char *value, void *userdata)
17 unsigned *const hash = (unsigned *)userdata;
25 /* scandirat() is not the underlying syscall, it's just a libc wrapper for getdents.
26 * There's significant differences between getdents and getdents64 (unlike, for
27 * example open64, which just passes some flag we don't really care about) so we
28 * wouldn't be able to just redirect one to the other. Therefore the simplest
29 * way not to duplicate code is to just wrap both scandirat variantes the same way. */
30 #define WRAP_SCANDIRAT(callname) \
31 int __real_##callname(int dirfd, const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)); \
32 int __wrap_##callname(int dirfd, const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) { \
33 return fail_scandirat ? -1 : __real_##callname(dirfd, dirp, namelist, filter, compar); \
35 static bool fail_scandirat;
36 WRAP_SCANDIRAT(scandirat)
37 WRAP_SCANDIRAT(scandirat64)
39 static bool fail_openat;
40 int __real_openat(int dirfd, const char *pathname, int flags, mode_t mode);
41 int __wrap_openat(int dirfd, const char *pathname, int flags, mode_t mode)
43 return fail_openat ? -1 : __real_openat(dirfd, pathname, flags, mode);
45 int __wrap_openat64(int dirfd, const char *pathname, int flags, mode_t mode)
47 return __wrap_openat(dirfd, pathname, flags, mode);
50 static bool fail_fdopen;
51 FILE *__real_fdopen(int fd, const char *mode);
52 FILE *__wrap_fdopen(int fd, const char *mode)
54 return fail_fdopen ? NULL : __real_fdopen(fd, mode);
56 FILE *__wrap_fdopen64(int fd, const char *mode)
58 return __wrap_fdopen(fd, mode);
61 static bool fail_open;
62 int __real_open(const char *pathname, int flags, mode_t mode);
63 int __wrap_open(const char *pathname, int flags, mode_t mode)
65 return fail_open ? -1 : __real_open(pathname, flags, mode);
67 int __wrap_open64(const char *pathname, int flags, mode_t mode)
69 return __wrap_open(pathname, flags, mode);
72 static bool fail_calloc;
73 void *__real_calloc(size_t nmemb, size_t size);
74 void *__wrap_calloc(size_t nmemb, size_t size)
76 return fail_calloc ? NULL : __real_calloc(nmemb, size);
82 struct log_config config;
84 setenv("DLOG_CONFIG_PATH", "./non_existent_file", 1);
85 assert(log_config_read(&config) == -ENOENT);
87 setenv("DLOG_CONFIG_PATH", "src/tests/test.conf", 1);
89 #define FAIL_EXTRA_CONF_CALL(callname) \
90 fail_##callname = true; \
91 assert(!log_config_read(&config)); \
92 assert(log_config_get(&config, "foo")); \
93 assert(!log_config_get(&config, "valid_extra_conf")); \
94 log_config_free(&config); \
95 fail_##callname = false
97 FAIL_EXTRA_CONF_CALL(scandirat);
98 FAIL_EXTRA_CONF_CALL(openat);
99 FAIL_EXTRA_CONF_CALL(fdopen);
100 FAIL_EXTRA_CONF_CALL(open);
102 #undef FAIL_EXTRA_CONF_CALL
104 assert(!log_config_read(&config));
106 /* test if key retrieval works first (needed for set tests) */
107 get = log_config_get(&config, "foo");
109 assert(!strncmp(get, "bar", 4));
110 assert(!log_config_get(&config, "baz"));
111 assert(!log_config_get(&config, "tony"));
113 assert(!log_config_get(&config, "nitz"));
115 get = log_config_get(&config, "valid_extra_conf");
117 assert(!strncmp(get, "123", 4));
118 assert(log_config_get_int(&config, "valid_extra_conf", 567) == 123);
120 get = log_config_get(&config, "invalid_extra_conf");
122 assert(log_config_get_int(&config, "invalid_extra_conf", 678) == 678);
124 /* test key length limits */
125 char long_key[1000] = { [0 ... 998] = 'a', [999] = '\0' };
126 get = log_config_get(&config, long_key);
129 /* test existing key modification */
130 log_config_set(&config, "foo", "quux");
131 get = log_config_get(&config, "foo");
133 assert(strncmp(get, "bar", 4));
134 assert(!strncmp(get, "quux", 5));
136 /* test new key addition */
137 log_config_set(&config, "test_add_key", "ok");
138 get = log_config_get(&config, "test_add_key");
140 assert(!strncmp(get, "ok", 3));
142 log_config_set(&config, "test_enormous_numbers", "999999999999999999999999999999999999999999999999999999");
143 assert(log_config_get_int(&config, "test_enormous_numbers", 42) == 42);
145 /* test boolean conversion */
146 log_config_set(&config, "b_true" , "1");
147 log_config_set(&config, "b_false", "0");
148 log_config_set(&config, "b_none" , "foo");
150 assert(log_config_get_boolean(&config, "b_true" , true));
151 assert(log_config_get_boolean(&config, "b_true" , false));
152 assert(!log_config_get_boolean(&config, "b_false", true));
153 assert(!log_config_get_boolean(&config, "b_false", false));
154 assert(log_config_get_boolean(&config, "b_none" , true));
155 assert(!log_config_get_boolean(&config, "b_none" , false));
157 unsigned hash_original = 0U;
158 log_config_foreach(&config, conf_hash, &hash_original);
160 struct log_config copy = {NULL, NULL};
161 log_config_copy(©, &config);
163 unsigned hash_copy = 0U;
164 log_config_foreach(©, conf_hash, &hash_copy);
166 assert(hash_copy == hash_original);
168 assert(log_config_get_boolean(©, "b_true", false));
169 assert(log_config_remove(©, "b_true"));
170 assert(!log_config_remove(©, "b_true"));
171 assert(!log_config_get_boolean(©, "b_true", false));
172 assert(!log_config_remove(©, "we wtorki ser jest zielony"));
173 assert(!log_config_remove(©, "we wtorki ser jest zielony"));
175 log_config_free(©);
179 assert(!log_config_remove(©, "abc"));
183 log_config_set(©, "abc", "123");
185 assert(copy.begin == copy.last);
188 log_config_set(©, "fail", "lol");
190 assert(copy.begin == copy.last);
193 log_config_set(©, "def", "456");
196 assert(copy.begin != copy.last);
198 assert(log_config_remove(©, "def"));
200 assert(copy.begin == copy.last);
202 assert(log_config_remove(©, "abc"));
208 #define CHECK(ret, wanted, bufname, pipe, sorting) do { \
209 sorting_needed = !sorting; \
210 assert(ret == get_proper_sort_by(wanted, bufname, pipe, ©, &sorting_needed)); \
211 assert(sorting_needed == sorting); \
214 /* KMSG returns SENT_MONO no matter what,
215 * since that is the timestamp dmesg "sorts" on. */
216 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_KMSG, false, false);
217 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_KMSG, true, false);
218 log_config_set(©, "sort_by", "recv_real");
219 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_KMSG, false, false);
220 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_KMSG, true, false);
221 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_BUF_KMSG, false, false);
222 CHECK(DLOGUTIL_SORT_SENT_MONO, DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_BUF_KMSG, true, false);
223 log_config_remove(©, "sort_by");
225 /* Android Logger returns SENT_REAL no matter what, since that is
226 * the only timestamp available for that backend. */
227 CHECK(DLOGUTIL_SORT_SENT_REAL, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_MAIN, false, false);
228 log_config_set(©, "sort_by", "recv_real");
229 CHECK(DLOGUTIL_SORT_SENT_REAL, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_MAIN, false, false);
230 CHECK(DLOGUTIL_SORT_SENT_REAL, DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_BUF_MAIN, false, false);
231 log_config_remove(©, "sort_by");
233 // Pipe backend defaults to RECV_MONO but obeys the config.
234 CHECK(DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_MAIN, true, false);
235 log_config_set(©, "sort_by", "recv_real");
236 CHECK(DLOGUTIL_SORT_RECV_REAL, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_MAIN, true, false);
237 CHECK(DLOGUTIL_SORT_SENT_REAL, DLOGUTIL_SORT_SENT_REAL, DLOGUTIL_BUF_MAIN, true, true);
238 log_config_remove(©, "sort_by");
239 CHECK(DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_BUF_MAIN, true, false);
240 CHECK(DLOGUTIL_SORT_RECV_MONO, DLOGUTIL_SORT_DEFAULT , DLOGUTIL_BUF_MAIN, true, false);