2 * Copyright (c) 2018, Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "../src/logger/log_storage.h"
24 #define SINGLE_LOG_SIZE(str) (sizeof(dlogutil_entry_s)+sizeof(str)+1)
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}
31 static bool fail_malloc = false;
33 void *__real_malloc(size_t size);
34 void *__wrap_malloc(size_t size)
36 return fail_malloc ? NULL : __real_malloc(size);
39 void dont_call_this_callback(const dlogutil_entry_s *le, void *user_data)
44 int callback_count = 0;
46 void callback_check_msg(const dlogutil_entry_s *le, void *user_data)
51 const char *s = user_data;
52 assert(strcmp(le->msg, s) == 0);
58 void callback_check_sec(const dlogutil_entry_s *le, void *user_data)
62 assert(le->sec_sent_mono == check_sec);
66 void callback_count_inc(const dlogutil_entry_s *le, void *user_data)
73 void test_add_logs(log_storage *s1, unsigned cnt, unsigned sec_base, bool inc, unsigned nsec, bool set_check)
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);
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));
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));
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));
100 struct dlogutil_entry_with_msg e1 = LE_SM(STR1, sec_to_set, nsec);
101 assert(log_storage_add_new_entry(s1, &e1.header));
108 void test_reader_get_new_entry(log_storage_reader *r, unsigned sec_to_check)
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);
117 switch (log_storage_get_sorting_order(s)) {
118 case DLOGUTIL_SORT_RECV_REAL:
119 entry_sec = le->sec_recv_real;
121 case DLOGUTIL_SORT_RECV_MONO:
122 entry_sec = le->sec_recv_mono;
124 case DLOGUTIL_SORT_SENT_REAL:
125 entry_sec = le->sec_sent_real;
128 entry_sec = le->sec_sent_mono;
132 assert(entry_sec == sec_to_check);
135 void test_reader_get_new_entries(log_storage_reader *r, unsigned cnt, unsigned check_base)
139 for (unsigned int i = 0; i < cnt; i++)
140 test_reader_get_new_entry(r, check_base+i+1);
145 /************* TEST 1 ***************/
146 /* Small storage, calling callbacks on removing log entries */
147 // create storage so small that no log is stored,
149 const int CNT = 1000;
151 log_storage *s1 = log_storage_create(1, DLOGUTIL_SORT_SENT_MONO);
153 assert(log_storage_get_capacity(s1) == 1);
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));
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);
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));
167 log_storage_release_reader(r1);
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);
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);
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);
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));
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);
194 log_storage_release_reader(r1);
195 log_storage_release_reader(r2);
196 log_storage_free(s1);
199 /************* TEST 2 ***************/
200 /* Basic test checking normal operation - add entries, read entries */
202 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
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);
211 const int CNT = 1000;
213 test_add_logs(s1, CNT, 0, true, 0, false);
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);
220 assert(log_storage_reader_get_new_entry(r1) == NULL);
221 assert(log_storage_reader_get_new_entry(r2) == NULL);
223 log_storage_release_reader(r1);
224 log_storage_release_reader(r2);
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);
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);
236 assert(log_storage_reader_get_new_entry(r1) == NULL);
237 assert(log_storage_reader_get_new_entry(r2) == NULL);
239 assert(callback_count == 0);
242 log_storage_release_reader(r1);
243 log_storage_release_reader(r2);
244 log_storage_free(s1);
247 /************* TEST 3 ***************/
248 /* Basic test checking normal operation - add entries, read entries */
249 /* Additionally check sorting */
251 const int CNT = 1000;
254 for (int i = 0; i < DLOGUTIL_SORT_DEFAULT; i++) {
255 log_storage *s = log_storage_create(1000000, i);
257 log_storage_reader *r = log_storage_new_reader(s, false, false, dont_call_this_callback, NULL);
260 // put logs in reverse order
261 test_add_logs(s, CNT, CNT+1, false, 0, false);
263 // check if the storage sorted the logs
264 test_reader_get_new_entries(r, CNT, 0);
266 assert(log_storage_reader_get_new_entry(r) == NULL);
268 assert(callback_count == 0);
270 log_storage_release_reader(r);
274 /************* TEST 4 ***************/
275 /* Basic test checking normal operation - add entries, read entries */
276 /* Additionally check calling callbacks while sorting */
278 const int CNT = 1000;
280 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
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);
287 // put logs in reverse order
288 test_add_logs(s1, CNT, 2*CNT+1, false, 0, false);
290 // check if the storage sorted the logs
291 test_reader_get_new_entries(r1, CNT, CNT);
293 // put more logs in reverse order
294 test_add_logs(s1, CNT, CNT+1, false, 0, true);
296 assert(log_storage_reader_get_new_entry(r1) == NULL);
298 // check the second reader
299 test_reader_get_new_entries(r2, 2*CNT, 0);
301 assert(log_storage_reader_get_new_entry(r2) == NULL);
303 assert(callback_count == CNT);
305 log_storage_release_reader(r1);
306 log_storage_release_reader(r2);
307 log_storage_free(s1);
309 /************* TEST 5 ***************/
310 /* Check if after clearing it still works */
312 const int CNT = 1000;
314 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
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);
324 test_add_logs(s1, 2*CNT, 0, true, 0, false);
326 // keep reader r1 at the start of the logs
328 // get reader r2 halfway through
329 test_reader_get_new_entries(r2, CNT, 0);
331 // get reader r3 to the end
332 test_reader_get_new_entries(r3, 2*CNT, 0);
335 log_storage_clear(s1);
337 assert(callback_count == 3*CNT);
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);
344 test_add_logs(s1, CNT, 0, true, 0, false);
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);
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);
357 log_storage_release_reader(r1);
358 log_storage_release_reader(r2);
359 log_storage_release_reader(r3);
360 log_storage_free(s1);
362 /************* TEST 6 ***************/
363 /* Dumping/one-shot reader */
365 const int CNT = 1000;
367 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
369 log_storage_reader *r1 = log_storage_new_reader(s1, true, false, dont_call_this_callback, NULL);
372 assert(!log_storage_reader_is_new_entry_available(r1));
373 assert(log_storage_reader_get_new_entry(r1) == NULL);
375 log_storage_release_reader(r1);
378 test_add_logs(s1, CNT, CNT, true, 0, false);
380 r1 = log_storage_new_reader(s1, true, false, dont_call_this_callback, NULL);
383 test_reader_get_new_entries(r1, CNT, CNT);
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);
390 test_add_logs(s1, CNT, 2*CNT, true, 0, false);
392 // so, now there are 2*CNT logs in the storage
393 r1 = log_storage_new_reader(s1, true, false, callback_check_sec, NULL);
396 // add even more logs
397 test_add_logs(s1, CNT, 3*CNT, true, 0, false);
399 // now, there are 2*CNT logs for this reader, and 1*CNT later logs
400 test_reader_get_new_entries(r1, CNT, CNT);
402 // the reader has read half of "his" logs
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);
408 // read the remaining logs
409 test_reader_get_new_entries(r1, CNT, 2*CNT);
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);
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);
419 assert(!log_storage_reader_is_new_entry_available(r1));
420 assert(log_storage_reader_get_new_entry(r1) == NULL);
422 // adding later logs should not give him those logs
423 test_add_logs(s1, CNT, 4*CNT, true, 1, true);
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);
429 // there should be no reader actions while adding further logs, without any readers
431 test_add_logs(s1, CNT, 0, true, 2, false);
432 test_add_logs(s1, CNT, 5*CNT, true, 1, false);
434 log_storage_free(s1);
436 /************* TEST 7 ***************/
437 /* Test basic bookkeeping */
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);
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));
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));
455 log_storage_release_reader(r1);
457 /************* TEST 8 ***************/
458 /* Test syscall failure handling */
461 log_storage *s1 = log_storage_create(10000, DLOGUTIL_SORT_SENT_MONO);
465 s1 = log_storage_create(10000, DLOGUTIL_SORT_SENT_MONO);
468 log_storage_reader *const r1 = log_storage_new_reader(s1, false, false, callback_count_inc, NULL);
470 struct dlogutil_entry_with_msg le1 = LE_RR(STR1, 123, 456);
472 assert(!log_storage_add_new_entry(s1, &le1.header));
476 log_storage_free(s1);
477 assert(callback_count == 0);
479 log_storage_release_reader(r1);
482 /************* TEST 9 ***************/
483 /* test get_usage & monitor mode */
485 const int CNT = 1000;
486 log_storage *s1 = log_storage_create(1000000, DLOGUTIL_SORT_SENT_MONO);
489 assert(0 == log_storage_get_usage(s1));
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));
495 assert((SINGLE_LOG_SIZE(STR1) * CNT) == log_storage_get_usage(s1));
497 log_storage_reader *r1 = log_storage_new_reader(s1, false, true, dont_call_this_callback, NULL);
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));
504 log_storage_release_reader(r1);
505 log_storage_free(s1);