9f55e164cc75378be5bf06bcdefa397a04e3b6f8
[platform/core/system/dlog.git] / src / tests / test_logger_log_storage.c
1 /*
2  * Copyright (c) 2018, Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "../src/logger/log_storage.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <assert.h>
21 #include <limits.h>
22
23 #define STR1 "a"
24 #define SINGLE_LOG_SIZE(str) (sizeof(dlogutil_entry_s)+sizeof(str)+1)
25
26 #define LE_SM(str, tsec, tnsec) {{SINGLE_LOG_SIZE(str), 0, 0, 1, 1, (tsec), (tnsec), 0U, 0U, 0U, 0U, 0U, 0U, 0U}, str}
27 #define LE_SR(str, tsec, tnsec) {{SINGLE_LOG_SIZE(str), 0, 0, 1, 1, 0U, 0U, (tsec), (tnsec), 0U, 0U, 0U, 0U, 0U}, str}
28 #define LE_RM(str, tsec, tnsec) {{SINGLE_LOG_SIZE(str), 0, 0, 1, 1, 0U, 0U, 0U, 0U, (tsec), (tnsec), 0U, 0U, 0U}, str}
29 #define LE_RR(str, tsec, tnsec) {{SINGLE_LOG_SIZE(str), 0, 0, 1, 1, 0U, 0U, 0U, 0U, 0U, 0U, (tsec), (tnsec), 0U}, str}
30
31 static bool fail_malloc = false;
32
33 void *__real_malloc(size_t size);
34 void *__wrap_malloc(size_t size)
35 {
36         return fail_malloc ? NULL : __real_malloc(size);
37 }
38
39 void dont_call_this_callback(const dlogutil_entry_s *le, void *user_data)
40 {
41         assert(false);
42 }
43
44 int callback_count = 0;
45
46 void callback_check_msg(const dlogutil_entry_s *le, void *user_data)
47 {
48         assert(le);
49         assert(user_data);
50
51         const char *s = user_data;
52         assert(strcmp(le->msg, s) == 0);
53         callback_count++;
54 }
55
56 int check_sec = 0;
57
58 void callback_check_sec(const dlogutil_entry_s *le, void *user_data)
59 {
60         assert(le);
61
62         assert(le->sec_sent_mono == check_sec);
63         callback_count++;
64 }
65
66 void callback_count_inc(const dlogutil_entry_s *le, void *user_data)
67 {
68         assert(le);
69
70         callback_count++;
71 }
72
73 void test_add_logs(log_storage *s1, unsigned cnt, unsigned sec_base, bool inc, unsigned nsec, bool set_check)
74 {
75         assert(s1);
76
77         int incr = inc ? 1 : -1;
78         for (unsigned int i = 0; i < cnt; i++) {
79                 // identify each log by seconds field
80                 unsigned sec_to_set = sec_base+incr*(i+1);
81                 if (set_check)
82                         check_sec = sec_to_set;
83                 switch (log_storage_get_sorting_order(s1)) {
84                 case DLOGUTIL_SORT_RECV_REAL: {
85                         struct dlogutil_entry_with_msg e1 = LE_RR(STR1, sec_to_set, nsec);
86                         assert(log_storage_add_new_entry(s1, &e1.header));
87                         break;
88                 }
89                 case DLOGUTIL_SORT_RECV_MONO: {
90                         struct dlogutil_entry_with_msg e1 = LE_RM(STR1, sec_to_set, nsec);
91                         assert(log_storage_add_new_entry(s1, &e1.header));
92                         break;
93                 }
94                 case DLOGUTIL_SORT_SENT_REAL: {
95                         struct dlogutil_entry_with_msg e1 = LE_SR(STR1, sec_to_set, nsec);
96                         assert(log_storage_add_new_entry(s1, &e1.header));
97                         break;
98                 }
99                 default: {
100                         struct dlogutil_entry_with_msg e1 = LE_SM(STR1, sec_to_set, nsec);
101                         assert(log_storage_add_new_entry(s1, &e1.header));
102                         break;
103                 }
104                 }
105         }
106 }
107
108 void test_reader_get_new_entry(log_storage_reader *r, unsigned sec_to_check)
109 {
110         assert(r);
111
112         const struct log_storage *s = log_storage_reader_get_storage(r);
113         const dlogutil_entry_s *le = log_storage_reader_get_new_entry(r);
114         assert(le);
115         assert(s);
116         int32_t entry_sec;
117         switch (log_storage_get_sorting_order(s)) {
118         case DLOGUTIL_SORT_RECV_REAL:
119                 entry_sec = le->sec_recv_real;
120                 break;
121         case DLOGUTIL_SORT_RECV_MONO:
122                 entry_sec = le->sec_recv_mono;
123                 break;
124         case DLOGUTIL_SORT_SENT_REAL:
125                 entry_sec = le->sec_sent_real;
126                 break;
127         default:
128                 entry_sec = le->sec_sent_mono;
129                 break;
130         }
131
132         assert(entry_sec == sec_to_check);
133 }
134
135 void test_reader_get_new_entries(log_storage_reader *r, unsigned cnt, unsigned check_base)
136 {
137         assert(r);
138
139         for (unsigned int i = 0; i < cnt; i++)
140                 test_reader_get_new_entry(r, check_base+i+1);
141 }
142
143 int main()
144 {
145         /************* TEST 1 ***************/
146         /* Small storage, calling callbacks on removing log entries */
147         // create storage so small that no log is stored,
148         {
149                 const int CNT = 1000;
150
151                 log_storage *s1 = log_storage_create(1, DLOGUTIL_SORT_SENT_MONO);
152                 assert(s1);
153                 assert(log_storage_get_capacity(s1) == 1);
154
155                 // add entry - it should be released immediately
156                 struct dlogutil_entry_with_msg e1 = LE_SM(STR1, 1000U, 1000U);
157                 assert(log_storage_add_new_entry(s1, &e1.header));
158
159                 // add reader - no callback should be called
160                 log_storage_reader *r1 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
161                 assert(r1);
162                 // check there is no log entry stored
163                 assert(!log_storage_reader_is_new_entry_available(r1));
164                 assert(NULL == log_storage_reader_get_new_entry(r1));
165
166                 // remove the reader
167                 log_storage_release_reader(r1);
168
169                 // add reader with callback - when a log entry is added, a callback should be called
170                 r1 = log_storage_new_reader(s1, false, false, callback_check_msg, STR1);
171                 assert(r1);
172                 for (int i = 0; i < CNT; i++) {
173                         assert(log_storage_add_new_entry(s1, &e1.header));
174                         // check that each time log was added, the callback was called
175                         assert(callback_count == i+1);
176                 }
177
178                 // add second reader - now there should be twice as much calls to the callback
179                 log_storage_reader *r2 = log_storage_new_reader(s1, false, false, callback_check_msg, STR1);
180                 assert(r2);
181                 callback_count = 0;
182                 for (int i = 0; i < CNT; i++) {
183                         assert(log_storage_add_new_entry(s1, &e1.header));
184                         assert(callback_count == 2*(i+1));
185                 }
186
187                 assert(log_storage_reader_get_new_entry(r1) == NULL);
188                 assert(log_storage_reader_get_new_entry(r2) == NULL);
189                 log_storage_clear(s1);
190                 assert(log_storage_reader_get_new_entry(r1) == NULL);
191                 assert(log_storage_reader_get_new_entry(r2) == NULL);
192
193                 // cleanup
194                 log_storage_release_reader(r1);
195                 log_storage_release_reader(r2);
196                 log_storage_free(s1);
197         }
198
199         /************* TEST 2 ***************/
200         /* Basic test checking normal operation - add entries, read entries */
201         {
202                 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
203                 assert(s1);
204                 callback_count = 0;
205
206                 log_storage_reader *r1 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
207                 log_storage_reader *r2 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
208                 assert(r1);
209                 assert(r2);
210
211                 const int CNT = 1000;
212                 // add entries
213                 test_add_logs(s1, CNT, 0, true, 0, false);
214
215                 // read by both readers, alternately
216                 for (int i = 0; i < CNT; i++) {
217                         test_reader_get_new_entry(r1, i+1);
218                         test_reader_get_new_entry(r2, i+1);
219                 }
220                 assert(log_storage_reader_get_new_entry(r1) == NULL);
221                 assert(log_storage_reader_get_new_entry(r2) == NULL);
222
223                 log_storage_release_reader(r1);
224                 log_storage_release_reader(r2);
225
226                 // create two new readers
227                 r1 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
228                 r2 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
229                 assert(r1);
230                 assert(r2);
231
232                 // read logs by both readers, sequentially
233                 test_reader_get_new_entries(r1, CNT, 0);
234                 test_reader_get_new_entries(r2, CNT, 0);
235
236                 assert(log_storage_reader_get_new_entry(r1) == NULL);
237                 assert(log_storage_reader_get_new_entry(r2) == NULL);
238
239                 assert(callback_count == 0);
240
241                 // cleanup
242                 log_storage_release_reader(r1);
243                 log_storage_release_reader(r2);
244                 log_storage_free(s1);
245         }
246
247         /************* TEST 3 ***************/
248         /* Basic test checking normal operation - add entries, read entries */
249         /* Additionally check sorting */
250         {
251                 const int CNT = 1000;
252                 callback_count = 0;
253
254                 for (int i = 0; i < DLOGUTIL_SORT_DEFAULT; i++) {
255                         log_storage *s = log_storage_create(1000000, i);
256                         assert(s);
257                         log_storage_reader *r = log_storage_new_reader(s, false, false, dont_call_this_callback, NULL);
258                         assert(r);
259
260                         // put logs in reverse order
261                         test_add_logs(s, CNT, CNT+1, false, 0, false);
262
263                         // check if the storage sorted the logs
264                         test_reader_get_new_entries(r, CNT, 0);
265
266                         assert(log_storage_reader_get_new_entry(r) == NULL);
267
268                         assert(callback_count == 0);
269
270                         log_storage_release_reader(r);
271                         log_storage_free(s);
272                 }
273         }
274         /************* TEST 4 ***************/
275         /* Basic test checking normal operation - add entries, read entries */
276         /* Additionally check calling callbacks while sorting */
277         {
278                 const int CNT = 1000;
279                 callback_count = 0;
280                 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
281                 assert(s1);
282                 log_storage_reader *r1 = log_storage_new_reader(s1, false, false, callback_check_sec, NULL);
283                 log_storage_reader *r2 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
284                 assert(r1);
285                 assert(r2);
286
287                 // put logs in reverse order
288                 test_add_logs(s1, CNT, 2*CNT+1, false, 0, false);
289
290                 // check if the storage sorted the logs
291                 test_reader_get_new_entries(r1, CNT, CNT);
292
293                 // put more logs in reverse order
294                 test_add_logs(s1, CNT, CNT+1, false, 0, true);
295
296                 assert(log_storage_reader_get_new_entry(r1) == NULL);
297
298                 // check the second reader
299                 test_reader_get_new_entries(r2, 2*CNT, 0);
300
301                 assert(log_storage_reader_get_new_entry(r2) == NULL);
302
303                 assert(callback_count == CNT);
304
305                 log_storage_release_reader(r1);
306                 log_storage_release_reader(r2);
307                 log_storage_free(s1);
308         }
309         /************* TEST 5 ***************/
310         /* Check if after clearing it still works */
311         {
312                 const int CNT = 1000;
313                 callback_count = 0;
314                 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
315                 assert(s1);
316                 log_storage_reader *r1 = log_storage_new_reader(s1, false, false, callback_count_inc, NULL);
317                 log_storage_reader *r2 = log_storage_new_reader(s1, false, false, callback_count_inc, NULL);
318                 log_storage_reader *r3 = log_storage_new_reader(s1, false, false, dont_call_this_callback, NULL);
319                 assert(r1);
320                 assert(r2);
321                 assert(r3);
322
323                 // add logs
324                 test_add_logs(s1, 2*CNT, 0, true, 0, false);
325
326                 // keep reader r1 at the start of the logs
327
328                 // get reader r2 halfway through
329                 test_reader_get_new_entries(r2, CNT, 0);
330
331                 // get reader r3 to the end
332                 test_reader_get_new_entries(r3, 2*CNT, 0);
333
334                 // clear the storage
335                 log_storage_clear(s1);
336
337                 assert(callback_count == 3*CNT);
338
339                 assert(log_storage_reader_get_new_entry(r1) == NULL);
340                 assert(log_storage_reader_get_new_entry(r2) == NULL);
341                 assert(log_storage_reader_get_new_entry(r3) == NULL);
342
343                 // add logs
344                 test_add_logs(s1, CNT, 0, true, 0, false);
345
346                 // read by all the readers, alternately
347                 for (int i = 0; i < CNT; i++) {
348                         test_reader_get_new_entry(r1, i+1);
349                         test_reader_get_new_entry(r2, i+1);
350                         test_reader_get_new_entry(r3, i+1);
351                 }
352
353                 assert(log_storage_reader_get_new_entry(r1) == NULL);
354                 assert(log_storage_reader_get_new_entry(r2) == NULL);
355                 assert(log_storage_reader_get_new_entry(r3) == NULL);
356
357                 log_storage_release_reader(r1);
358                 log_storage_release_reader(r2);
359                 log_storage_release_reader(r3);
360                 log_storage_free(s1);
361         }
362         /************* TEST 6 ***************/
363         /* Dumping/one-shot reader */
364         {
365                 const int CNT = 1000;
366                 callback_count = 0;
367                 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
368                 assert(s1);
369                 log_storage_reader *r1 = log_storage_new_reader(s1, true, false, dont_call_this_callback, NULL);
370                 assert(r1);
371
372                 assert(!log_storage_reader_is_new_entry_available(r1));
373                 assert(log_storage_reader_get_new_entry(r1) == NULL);
374
375                 log_storage_release_reader(r1);
376
377                 // add logs
378                 test_add_logs(s1, CNT, CNT, true, 0, false);
379
380                 r1 = log_storage_new_reader(s1, true, false, dont_call_this_callback, NULL);
381                 assert(r1);
382
383                 test_reader_get_new_entries(r1, CNT, CNT);
384
385                 assert(!log_storage_reader_is_new_entry_available(r1));
386                 assert(log_storage_reader_get_new_entry(r1) == NULL);
387                 log_storage_release_reader(r1);
388
389                 // add more logs
390                 test_add_logs(s1, CNT, 2*CNT, true, 0, false);
391
392                 // so, now there are 2*CNT logs in the storage
393                 r1 = log_storage_new_reader(s1, true, false, callback_check_sec, NULL);
394                 assert(r1);
395
396                 // add even more logs
397                 test_add_logs(s1, CNT, 3*CNT, true, 0, false);
398
399                 // now, there are 2*CNT logs for this reader, and 1*CNT later logs
400                 test_reader_get_new_entries(r1, CNT, CNT);
401
402                 // the reader has read half of "his" logs
403
404                 // add even even more logs, but earlier
405                 // the logs should be passed to the reader by the callback
406                 test_add_logs(s1, CNT, 0, true, 0, true);
407
408                 // read the remaining logs
409                 test_reader_get_new_entries(r1, CNT, 2*CNT);
410
411                 assert(!log_storage_reader_is_new_entry_available(r1));
412                 assert(log_storage_reader_get_new_entry(r1) == NULL);
413                 assert(callback_count == CNT);
414
415                 // reader has read all his logs
416                 // but adding earlier logs should still give him those logs, with callback
417                 test_add_logs(s1, CNT, 0, true, 1, true);
418
419                 assert(!log_storage_reader_is_new_entry_available(r1));
420                 assert(log_storage_reader_get_new_entry(r1) == NULL);
421
422                 // adding later logs should not give him those logs
423                 test_add_logs(s1, CNT, 4*CNT, true, 1, true);
424
425                 assert(!log_storage_reader_is_new_entry_available(r1));
426                 assert(log_storage_reader_get_new_entry(r1) == NULL);
427                 log_storage_release_reader(r1);
428
429                 // there should be no reader actions while adding further logs, without any readers
430                 check_sec = 0;
431                 test_add_logs(s1, CNT, 0, true, 2, false);
432                 test_add_logs(s1, CNT, 5*CNT, true, 1, false);
433
434                 log_storage_free(s1);
435         }
436         /************* TEST 7 ***************/
437         /* Test basic bookkeeping */
438         {
439                 log_storage *const s1 = log_storage_create(10000, DLOGUTIL_SORT_SENT_MONO);
440                 log_storage_reader *const r1 = log_storage_new_reader(s1, false, false, callback_count_inc, NULL);
441
442                 struct dlogutil_entry_with_msg le1 = LE_RR(STR1, 123, 456);
443                 assert(le1.header.len * 0 == log_storage_reader_get_ready_bytes(r1));
444                 assert(log_storage_add_new_entry(s1, &le1.header));
445                 assert(le1.header.len * 1 == log_storage_reader_get_ready_bytes(r1));
446                 assert(log_storage_add_new_entry(s1, &le1.header));
447                 assert(le1.header.len * 2 == log_storage_reader_get_ready_bytes(r1));
448
449                 callback_count = 0;
450                 log_storage_free(s1);
451                 assert(callback_count == 2);
452                 assert(!log_storage_reader_is_new_entry_available(r1));
453                 assert(0 == log_storage_reader_get_ready_bytes(r1));
454
455                 log_storage_release_reader(r1);
456         }
457         /************* TEST 8 ***************/
458         /* Test syscall failure handling */
459         {
460                 fail_malloc = true;
461                 log_storage *s1 = log_storage_create(10000, DLOGUTIL_SORT_SENT_MONO);
462                 assert(!s1);
463                 fail_malloc = false;
464
465                 s1 = log_storage_create(10000, DLOGUTIL_SORT_SENT_MONO);
466                 assert(s1);
467
468                 log_storage_reader *const r1 = log_storage_new_reader(s1, false, false, callback_count_inc, NULL);
469
470                 struct dlogutil_entry_with_msg le1 = LE_RR(STR1, 123, 456);
471                 fail_malloc = true;
472                 assert(!log_storage_add_new_entry(s1, &le1.header));
473                 fail_malloc = false;
474
475                 callback_count = 0;
476                 log_storage_free(s1);
477                 assert(callback_count == 0);
478
479                 log_storage_release_reader(r1);
480         }
481
482         /************* TEST 9 ***************/
483         /* test get_usage & monitor mode */
484         {
485                 const int CNT = 1000;
486                 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
487                 assert(s1);
488
489                 assert(0 == log_storage_get_usage(s1));
490
491                 struct dlogutil_entry_with_msg e1 = LE_SM(STR1, 1000U, 1000U);
492                 for (int i = 0; i < CNT; i++)
493                         assert(log_storage_add_new_entry(s1, &e1.header));
494
495                 assert((SINGLE_LOG_SIZE(STR1) * CNT) == log_storage_get_usage(s1));
496
497                 log_storage_reader *r1 = log_storage_new_reader(s1, false, true, dont_call_this_callback, NULL);
498                 assert(r1);
499
500                 // in the monitor mode, old logs are not taken into consideration
501                 assert(!log_storage_reader_is_new_entry_available(r1));
502                 assert(NULL == log_storage_reader_get_new_entry(r1));
503
504                 log_storage_release_reader(r1);
505                 log_storage_free(s1);
506         }
507
508         return 0;
509 }