Replace () with (void) in function prototypes
[platform/core/system/dlog.git] / src / tests / filters.c
1 #include <assert.h>
2 #include <dlogutil-internal.h>
3 #include <logprint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 enum {
8         verbose = (1 << 0),
9         debug   = (1 << 1),
10         info    = (1 << 2),
11         warn    = (1 << 3),
12         error   = (1 << 4),
13         fatal   = (1 << 5),
14 };
15
16 int pid_tid_filter_list[] = {
17         1234,
18         2345,
19         34567,
20         98273545,
21         1,
22 };
23
24 /**
25  * @brief Checks if a log message with a tid is printed as expected
26  * @details Verify the log_should_print_line function returns the expected value
27  * @param[in] line The number of source code line in this file, printed in debug messages
28  * @param[in] p_filter The filter to work with
29  * @param[in] tid The tid to filter with
30  * @param[in] expected The expected result returned by log_should_print_line function
31  * @return 0 if the log_should_print_line returns the expected result, 1 otherwise
32  */
33 int check_print_line_tid_single(int line, struct log_filter *p_filter, pthread_t tid, bool expected)
34 {
35         struct dlogutil_entry_with_msg entry;
36
37         entry.msg[0] = '\0'; /* empty tag */
38         entry.msg[1] = '\0'; /* empty msg */
39         entry.header.tag_len = 0;
40         entry.header.pid = 0;
41         entry.header.tid = tid;
42         entry.header.priority = DLOG_DEBUG; // priority, for unmatched entries that have to face the global filter
43         entry.header.len = sizeof(dlogutil_entry_s) + 2;
44
45         if (expected != log_should_print_line(p_filter, &entry.header)) {
46                 printf("Check in line %d for tid %lu failed to return %d \n", line, tid,
47                         expected);
48                 return 1;
49         }
50         return 0;
51 }
52
53 /**
54  * @brief Checks if a log message if filtered properly for a group of tids
55  * @details Verify the log_should_print_line function returns the expected values
56  * @param[in] line The number of line in test, printed in debug messages
57  * @param[in] p_filter The filter to work with
58  * @param[in] tid The tid to filter with
59  * @return Number of tids for which log_should_print_line returns wrong answer
60  */
61
62 int check_print_line_tid(int line, struct log_filter *p_filter, pthread_t tid)
63 {
64         int result = 0;
65         for (size_t tid_no = 0; tid_no < NELEMS(pid_tid_filter_list); tid_no++)
66                 result += check_print_line_tid_single(line, p_filter, pid_tid_filter_list[tid_no], (pid_tid_filter_list[tid_no] == tid));
67         return result;
68 }
69
70 /**
71  * @brief Checks if a log message with a pid is printed as expected
72  * @details Verify the log_should_print_line function returns the expected value
73  * @param[in] line The number of source code line in this file, printed in debug messages
74  * @param[in] p_filter The filter to work with
75  * @param[in] pid The pid to filter with
76  * @param[in] expected The expected result returned by log_should_print_line function
77  * @return 0 if the log_should_print_line returns the expected result, 1 otherwise
78  */
79 int check_print_line_pid_single(int line, struct log_filter *p_filter, pid_t pid, bool expected)
80 {
81         struct dlogutil_entry_with_msg entry;
82
83         entry.msg[0] = '\0'; /* empty tag */
84         entry.msg[1] = '\0'; /* empty msg */
85         entry.header.tag_len = 0;
86         entry.header.tid = 0;
87         entry.header.pid = pid;
88         entry.header.priority = DLOG_DEBUG; // priority, for unmatched entries that have to face the global filter
89         entry.header.len = sizeof(dlogutil_entry_s) + 2;
90
91         if (expected != log_should_print_line(p_filter, &entry.header)) {
92                 printf("Check in line %d for pid %d failed to return %d \n", line, pid,
93                         expected);
94                 return 1;
95         }
96         return 0;
97 }
98
99 /**
100  * @brief Checks if a log message if filtered properly for a group of pids
101  * @details Verify the log_should_print_line function returns the expected values
102  * @param[in] line The number of line in test, printed in debug messages
103  * @param[in] p_filter The filter to work with
104  * @param[in] pid The pid to filter with
105  * @return Number of pids for which log_should_print_line returns wrong answer
106  */
107
108 int check_print_line_pid(int line, struct log_filter *p_filter, pid_t pid)
109 {
110         int result = 0;
111         for (size_t pid_no = 0; pid_no < NELEMS(pid_tid_filter_list); pid_no++)
112                 result += check_print_line_pid_single(line, p_filter, pid_tid_filter_list[pid_no], (pid_tid_filter_list[pid_no] == pid));
113         return result;
114 }
115
116 /**
117  * @brief Checks if a log message with a tag and priority is printed as expected
118  * @details Verify the log_should_print_line function returns the expected value
119  * @param[in] line The number of source code line in this file, printed in debug messages
120  * @param[in] p_filter The filter to work with
121  * @param[in] tag The message's tag
122  * @param[in] priority The message's priority
123  * @param[in] expected The expected result returned by log_should_print_line function
124  * @return 0 if the log_should_print_line returns the expected result, 1 otherwise
125  */
126 int check_print_line_tag_prior(int line, struct log_filter *p_filter, char *tag, int priority, bool expected)
127 {
128         struct dlogutil_entry_with_msg entry;
129
130         entry.header.tid = 0;
131         entry.header.pid = 0;
132         entry.header.priority = priority;
133         strncpy(entry.msg, tag, strlen(tag) + 1);
134         entry.msg[strlen(tag) + 1] = '\0'; // second NULL terminator: empty message
135         entry.header.len = sizeof(dlogutil_entry_s) + strlen(tag) + 2;
136
137         if (expected != log_should_print_line(p_filter, &entry.header)) {
138                 printf("Check in line %d for tag %s and priority %c failed to return %d \n", line, tag,
139                         filter_pri_to_char(priority), expected);
140                 return 1;
141         }
142         return 0;
143 }
144
145 /**
146  * @brief Checks if a log messages with a tag is printed ONLY for specified priorities
147  * @details Verify the log_should_print_line function returns the expected values
148  * @param[in] line The number of line in test, printed in debug messages
149  * @param[in] p_filter The filter to work with
150  * @param[in] tag The message's tag
151  * @param[in] priority The message's priorities which should be printed
152  * @return Number of priorities for which log_should_print_line returns wrong answer
153  */
154
155 int check_print_line_tag(int line, struct log_filter *p_filter, char *tag, int priors)
156 {
157         int result = 0;
158         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_VERBOSE, (priors & verbose) > 0);
159         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_DEBUG, (priors & debug) > 0);
160         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_INFO, (priors & info) > 0);
161         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_WARN, (priors & warn) > 0);
162         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_ERROR, (priors & error) > 0);
163         result += check_print_line_tag_prior(line, p_filter, tag, DLOG_FATAL, (priors & fatal) > 0);
164         return result;
165 }
166
167 int check_colons(void)
168 {
169         struct log_filter *const f = log_filter_new();
170         assert(f);
171
172         assert(log_add_filter_rule(f, "QWE:::Q:WE::WQE:WQE:W") == TIZEN_ERROR_NONE);
173         assert(log_add_filter_rule(f, "SD:A:DS:D:ASD:SA:D::D") == TIZEN_ERROR_NONE);
174         assert(log_add_filter_rule(f, ":::VXZVCXZVCXV::::::V") == TIZEN_ERROR_NONE);
175
176         int const result = check_print_line_tag(__LINE__, f, "QWE:::Q:WE::WQE:WQE",                          warn + error + fatal)
177                          + check_print_line_tag(__LINE__, f, "SD:A:DS:D:ASD:SA:D:",           debug + info + warn + error + fatal)
178                          + check_print_line_tag(__LINE__, f, ":::VXZVCXZVCXV:::::", verbose + debug + info + warn + error + fatal)
179         ;
180
181         // No colon at the end, this makes for '\0' priority
182         assert(log_add_filter_rule(f, "FOO:") == TIZEN_ERROR_INVALID_PARAMETER);
183
184         log_filter_free(f);
185
186         return result;
187 }
188
189 int main(void)
190 {
191         int err;
192         int result = 0;
193         char *tag, *tag_short, *tag_middle, *tag_long;
194         struct log_filter *p_filter;
195         struct dlogutil_entry_with_msg entry;
196
197         entry.header.tid = 0;
198         entry.header.pid = 0;
199
200         p_filter = log_filter_new();
201
202         tag = "random";
203         tag_short = "ab";
204         tag_middle = "abc";
205         tag_long = "abcde";
206
207
208         // Old tests - rewritten and kept for backward compatibility (before introduction '*' and '='  in filters
209
210         log_add_filter_rule(p_filter, "*:i"); //set global to info
211         result += check_print_line_tag(__LINE__, p_filter, tag, info | warn | error | fatal);
212         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
213         result += check_print_line_tag(__LINE__, p_filter, tag_middle, info | warn | error | fatal);
214         result += check_print_line_tag(__LINE__, p_filter, tag_long, info | warn | error | fatal);
215
216         log_add_filter_rule(p_filter, "*"); //set global to debug
217         result += check_print_line_tag(__LINE__, p_filter, tag, debug | info | warn | error | fatal);
218         result += check_print_line_tag(__LINE__, p_filter, tag_short, debug | info | warn | error | fatal);
219
220         log_add_filter_rule(p_filter, "*:v"); //set global to verbose
221         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
222         result += check_print_line_tag(__LINE__, p_filter, tag_short, verbose | debug | info | warn | error | fatal);
223
224         log_add_filter_rule(p_filter, "*:*"); //debug is default global level
225         result += check_print_line_tag(__LINE__, p_filter, tag, debug | info | warn | error | fatal);
226         result += check_print_line_tag(__LINE__, p_filter, tag_short, debug | info | warn | error | fatal);
227
228         log_add_filter_rule(p_filter, "*:i");
229         result += check_print_line_tag(__LINE__, p_filter, tag, info | warn | error | fatal);
230         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
231
232         log_add_filter_rule(p_filter, "random");
233         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
234         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
235
236         log_add_filter_rule(p_filter, "random:v");
237         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
238         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
239
240
241         log_add_filter_rule(p_filter, "random:d");
242         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
243         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
244
245         log_add_filter_rule(p_filter, "random:w");
246         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
247         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
248
249
250         log_add_filter_rule(p_filter, "crap:*");
251
252         static const size_t taglen = sizeof "crap" - 1;
253
254         entry.header.priority = DLOG_VERBOSE;
255         strncpy(entry.msg, "crap", taglen);
256         entry.msg[taglen] = '\0'; /* tag delimiter */
257         entry.msg[taglen + 1] = '\0'; /* empty msg */
258         entry.header.len = sizeof(dlogutil_entry_s) + taglen + 2;
259
260         assert(log_should_print_line(p_filter, &entry.header));
261         result += check_print_line_tag(__LINE__, p_filter, "crap", verbose | debug | info | warn | error | fatal);
262         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
263         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
264
265
266         //invalid expression
267         err = log_add_filter_rule(p_filter, "random:z");
268         assert(err < 0);
269         result += check_print_line_tag(__LINE__, p_filter, tag, verbose | debug | info | warn | error | fatal);
270         result += check_print_line_tag(__LINE__, p_filter, tag_short, info | warn | error | fatal);
271
272         // Adding empty filter string is possible and does not erase existing
273         log_add_filter_rule(p_filter, "issue550946:w");
274         err = log_filter_set_filterspec(p_filter, " ");
275         assert(err == 0);
276         result += check_print_line_tag(__LINE__, p_filter, "issue550946", warn | error | fatal);
277
278         // Adding a filter with wrong priority fails also when the tag was used before
279         err = log_filter_set_filterspec(p_filter, "*:s existing:d ");
280         assert(err == 0);
281         result += check_print_line_tag(__LINE__, p_filter, "existing", debug | info | warn | error | fatal);
282         err = log_filter_set_filterspec(p_filter, "*:s existing:z");
283         assert(err < 0);
284
285         log_filter_free(p_filter);
286
287         // Tests for '=' in filters
288
289         p_filter = log_filter_new();
290
291         log_add_filter_rule(p_filter, "pine:=i");
292         result += check_print_line_tag(__LINE__, p_filter, "pine", info);
293         result += check_print_line_tag(__LINE__, p_filter, tag, 0); //default policy for tag (slient) shall be used
294
295         log_add_filter_rule(p_filter, "pine:=e");
296         result += check_print_line_tag(__LINE__, p_filter, "pine", info | error);
297         result += check_print_line_tag(__LINE__, p_filter, tag, 0);
298
299         log_add_filter_rule(p_filter, "pine:i");
300         result += check_print_line_tag(__LINE__, p_filter, "pine", info | warn | error | fatal);
301         result += check_print_line_tag(__LINE__, p_filter, tag, 0);
302
303         log_add_filter_rule(p_filter, "oak:=i");
304         err = log_filter_set_filterspec(p_filter,  "alder:=v alder:=f");
305         assert(err == 0);
306         result += check_print_line_tag(__LINE__, p_filter, "pine", info | warn | error | fatal);
307         result += check_print_line_tag(__LINE__, p_filter, "alder", verbose | fatal);
308         result += check_print_line_tag(__LINE__, p_filter, tag, 0);
309
310         log_add_filter_rule(p_filter, "*:=v");
311         result += check_print_line_tag(__LINE__, p_filter, "pine", info | warn | error | fatal);
312         result += check_print_line_tag(__LINE__, p_filter, "alder", verbose | fatal);
313         result += check_print_line_tag(__LINE__, p_filter, tag, verbose);
314
315         log_filter_free(p_filter);
316
317         // Tests for '*' in the filters
318
319         p_filter = log_filter_new();
320
321         log_add_filter_rule(p_filter, "a:=v");
322         log_add_filter_rule(p_filter, "a*:w");
323         result += check_print_line_tag(__LINE__, p_filter, "a", verbose | warn | error | fatal);
324         result += check_print_line_tag(__LINE__, p_filter, "aa", warn | error | fatal);
325         result += check_print_line_tag(__LINE__, p_filter, "aaa", warn | error | fatal);
326         result += check_print_line_tag(__LINE__, p_filter, "aaab", warn | error | fatal);
327         result += check_print_line_tag(__LINE__, p_filter, "aaaaaaaaba",  warn | error | fatal);
328         result += check_print_line_tag(__LINE__, p_filter, "b", 0);
329         result += check_print_line_tag(__LINE__, p_filter, "ba", 0);
330
331         log_add_filter_rule(p_filter, "c?:w");
332         result += check_print_line_tag(__LINE__, p_filter, "c", 0);
333         result += check_print_line_tag(__LINE__, p_filter, "cx", 0);
334         result += check_print_line_tag(__LINE__, p_filter, "c?", warn | error | fatal);
335
336         log_add_filter_rule(p_filter, "zwxaaa*:e");
337         result += check_print_line_tag(__LINE__, p_filter, "z", 0);
338         result += check_print_line_tag(__LINE__, p_filter, "zx?*", 0);
339         result += check_print_line_tag(__LINE__, p_filter, "zwxaa", 0);
340         result += check_print_line_tag(__LINE__, p_filter, "zwxaab", 0);
341         result += check_print_line_tag(__LINE__, p_filter, "zwxaa?", 0);
342         result += check_print_line_tag(__LINE__, p_filter, "zwxaa*", 0);
343         result += check_print_line_tag(__LINE__, p_filter, "zwxaa?*", 0);
344         result += check_print_line_tag(__LINE__, p_filter, "zwxaaa", error | fatal);
345         result += check_print_line_tag(__LINE__, p_filter, "zwxaaaa", error | fatal);
346         result += check_print_line_tag(__LINE__, p_filter, "zwxaaab", error | fatal);
347         result += check_print_line_tag(__LINE__, p_filter, "zwxaaa*", error | fatal);
348
349         log_filter_free(p_filter);
350
351         // Tests for '*' and '=' in filters
352
353         p_filter = log_filter_new();
354         err = log_filter_set_filterspec(p_filter, "*:=v TORUN:=f TOR*:=d T*:=i torun:s *:i");
355         assert(err == 0);
356         result += check_print_line_tag(__LINE__, p_filter, "something", info | warn | error | fatal);
357         result += check_print_line_tag(__LINE__, p_filter, "t", info | warn | error | fatal);
358         result += check_print_line_tag(__LINE__, p_filter, "T", info);
359         result += check_print_line_tag(__LINE__, p_filter, "tor", info | warn | error | fatal);
360         result += check_print_line_tag(__LINE__, p_filter, "TOR", debug | info);
361         result += check_print_line_tag(__LINE__, p_filter, "TORUN", debug | info | fatal);
362         result += check_print_line_tag(__LINE__, p_filter, "something", info | warn | error | fatal);
363         result += check_print_line_tag(__LINE__, p_filter, "torun", 0);
364         log_filter_free(p_filter);
365
366         //Only *
367
368         p_filter = log_filter_new();
369         log_add_filter_rule(p_filter, "*");
370         result += check_print_line_tag(__LINE__, p_filter, tag, debug | info | warn | error | fatal);
371         log_filter_free(p_filter);
372
373         //No rules - no print lines
374
375         p_filter = log_filter_new();
376         result += check_print_line_tag(__LINE__, p_filter, tag, 0);
377         err = log_filter_set_filterspec(p_filter, "");
378         assert(err == 0);
379         result += check_print_line_tag(__LINE__, p_filter, tag, 0);
380         log_filter_free(p_filter);
381
382         //pid filtering rules
383         p_filter = log_filter_new();
384         result += check_print_line_pid(__LINE__, p_filter, 0);
385         err = log_filter_set_pid(p_filter, 9876);
386         assert(err == 0);
387         result += check_print_line_pid(__LINE__, p_filter, 9876);
388         err = log_filter_set_pid(p_filter, pid_tid_filter_list[0]);
389         assert(err == 0);
390         result += check_print_line_pid(__LINE__, p_filter, pid_tid_filter_list[0]);
391         log_filter_free(p_filter);
392
393         //tid filtering rules
394         p_filter = log_filter_new();
395         result += check_print_line_tid(__LINE__, p_filter, 0);
396         err = log_filter_set_tid(p_filter, 9876);
397         assert(err == 0);
398         result += check_print_line_tid(__LINE__, p_filter, 9876);
399         err = log_filter_set_tid(p_filter, pid_tid_filter_list[0]);
400         assert(err == 0);
401         result += check_print_line_tid(__LINE__, p_filter, pid_tid_filter_list[0]);
402         log_filter_free(p_filter);
403
404         result += check_colons();
405
406         if (result > 0)
407                 exit(-1);
408         return 0;
409 }