Replace () with (void) in function prototypes
[platform/core/system/dlog.git] / src / tests / config.c
1 // C
2 #include <assert.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 // POSIX
9 #include <dirent.h>
10 #include <fcntl.h>
11
12 // DLog
13 #include <logconfig.h>
14
15 static void conf_hash(const char *key, const char *value, void *userdata)
16 {
17         unsigned *const hash = (unsigned *)userdata;
18
19         while (*key)
20                 *hash += *(key++);
21         while (*value)
22                 *hash += *(value++);
23 }
24
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); \
34 }
35 static bool fail_scandirat;
36 WRAP_SCANDIRAT(scandirat)
37 WRAP_SCANDIRAT(scandirat64)
38
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)
42 {
43         return fail_openat ? -1 : __real_openat(dirfd, pathname, flags, mode);
44 }
45 int __wrap_openat64(int dirfd, const char *pathname, int flags, mode_t mode)
46 {
47         return __wrap_openat(dirfd, pathname, flags, mode);
48 }
49
50 static bool fail_fdopen;
51 FILE *__real_fdopen(int fd, const char *mode);
52 FILE *__wrap_fdopen(int fd, const char *mode)
53 {
54         return fail_fdopen ? NULL : __real_fdopen(fd, mode);
55 }
56 FILE *__wrap_fdopen64(int fd, const char *mode)
57 {
58         return __wrap_fdopen(fd, mode);
59 }
60
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)
64 {
65         return fail_open ? -1 : __real_open(pathname, flags, mode);
66 }
67 int __wrap_open64(const char *pathname, int flags, mode_t mode)
68 {
69         return __wrap_open(pathname, flags, mode);
70 }
71
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)
75 {
76         return fail_calloc ? NULL : __real_calloc(nmemb, size);
77 }
78
79 int main(void)
80 {
81         const char * get;
82         struct log_config config;
83
84         setenv("DLOG_CONFIG_PATH", "./non_existent_file", 1);
85         assert(log_config_read(&config) == -ENOENT);
86
87         setenv("DLOG_CONFIG_PATH", "src/tests/test.conf", 1);
88
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
96
97         FAIL_EXTRA_CONF_CALL(scandirat);
98         FAIL_EXTRA_CONF_CALL(openat);
99         FAIL_EXTRA_CONF_CALL(fdopen);
100         FAIL_EXTRA_CONF_CALL(open);
101
102 #undef FAIL_EXTRA_CONF_CALL
103
104         assert(!log_config_read(&config));
105
106         /* test if key retrieval works first (needed for set tests) */
107         get = log_config_get(&config, "foo");
108         assert(get);
109         assert(!strncmp(get, "bar", 4));
110         assert(!log_config_get(&config, "baz"));
111         assert(!log_config_get(&config, "tony"));
112
113         assert(!log_config_get(&config, "nitz"));
114
115         get = log_config_get(&config, "valid_extra_conf");
116         assert(get);
117         assert(!strncmp(get, "123", 4));
118         assert(log_config_get_int(&config, "valid_extra_conf", 567) == 123);
119
120         get = log_config_get(&config, "invalid_extra_conf");
121         assert(!get);
122         assert(log_config_get_int(&config, "invalid_extra_conf", 678) == 678);
123
124         /* test key length limits */
125         char long_key[1000] = { [0 ... 998] = 'a', [999] = '\0' };
126         get = log_config_get(&config, long_key);
127         assert(!get);
128
129         /* test existing key modification */
130         log_config_set(&config, "foo", "quux");
131         get = log_config_get(&config, "foo");
132         assert(get);
133         assert(strncmp(get, "bar", 4));
134         assert(!strncmp(get, "quux", 5));
135
136         /* test new key addition */
137         log_config_set(&config, "test_add_key", "ok");
138         get = log_config_get(&config, "test_add_key");
139         assert(get);
140         assert(!strncmp(get, "ok", 3));
141
142         log_config_set(&config, "test_enormous_numbers", "999999999999999999999999999999999999999999999999999999");
143         assert(log_config_get_int(&config, "test_enormous_numbers", 42) == 42);
144
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");
149
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));
156
157         unsigned hash_original = 0U;
158         log_config_foreach(&config, conf_hash, &hash_original);
159
160         struct log_config copy = {NULL, NULL};
161         log_config_copy(&copy, &config);
162
163         unsigned hash_copy = 0U;
164         log_config_foreach(&copy, conf_hash, &hash_copy);
165
166         assert(hash_copy == hash_original);
167
168         assert(log_config_get_boolean(&copy, "b_true", false));
169         assert(log_config_remove(&copy, "b_true"));
170         assert(!log_config_remove(&copy, "b_true"));
171         assert(!log_config_get_boolean(&copy, "b_true", false));
172         assert(!log_config_remove(&copy, "we wtorki ser jest zielony"));
173         assert(!log_config_remove(&copy, "we wtorki ser jest zielony"));
174
175         log_config_free(&copy);
176         assert(!copy.begin);
177         assert(!copy.last);
178
179         assert(!log_config_remove(&copy, "abc"));
180         assert(!copy.begin);
181         assert(!copy.last);
182
183         log_config_set(&copy, "abc", "123");
184         assert(copy.begin);
185         assert(copy.begin == copy.last);
186
187         fail_calloc = true;
188         log_config_set(&copy, "fail", "lol");
189         assert(copy.begin);
190         assert(copy.begin == copy.last);
191         fail_calloc = false;
192
193         log_config_set(&copy, "def", "456");
194         assert(copy.last);
195         assert(copy.begin);
196         assert(copy.begin != copy.last);
197
198         assert(log_config_remove(&copy, "def"));
199         assert(copy.begin);
200         assert(copy.begin == copy.last);
201
202         assert(log_config_remove(&copy, "abc"));
203         assert(!copy.begin);
204         assert(!copy.last);
205
206         bool sorting_needed;
207
208 #define CHECK(ret, wanted, bufname, pipe, sorting) do { \
209         sorting_needed = !sorting; \
210         assert(ret == get_proper_sort_by(wanted, bufname, pipe, &copy, &sorting_needed)); \
211         assert(sorting_needed == sorting); \
212 } while (0)
213
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(&copy, "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(&copy, "sort_by");
224
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(&copy, "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(&copy, "sort_by");
232
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(&copy, "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(&copy, "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);
241
242 #undef CHECK
243         return 0;
244 }