1 /*
2 * Copyright (C) 2013-2014 The Android Open Source Project
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
17 #include <fcntl.h>
18 #include <inttypes.h>
19 #include <signal.h>
20
21 #include <cutils/properties.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24 #include <log/logger.h>
25 #include <log/log_read.h>
26 #include <log/logprint.h>
27
28 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
29 // non-syscall libs. Since we are only using this in the emergency of
30 // a signal to stuff a terminating code into the logs, we will spin rather
31 // than try a usleep.
32 #define LOG_FAILURE_RETRY(exp) ({ \
33 typeof (exp) _rc; \
34 do { \
35 _rc = (exp); \
36 } while (((_rc == -1) \
37 && ((errno == EINTR) \
38 || (errno == EAGAIN))) \
39 || (_rc == -EINTR) \
40 || (_rc == -EAGAIN)); \
41 _rc; })
42
TEST(liblog,__android_log_buf_print)43 TEST(liblog, __android_log_buf_print) {
44 EXPECT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO,
45 "TEST__android_log_buf_print",
46 "radio"));
47 usleep(1000);
48 EXPECT_LT(0, __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
49 "TEST__android_log_buf_print",
50 "system"));
51 usleep(1000);
52 EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
53 "TEST__android_log_buf_print",
54 "main"));
55 usleep(1000);
56 }
57
TEST(liblog,__android_log_buf_write)58 TEST(liblog, __android_log_buf_write) {
59 EXPECT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO,
60 "TEST__android_log_buf_write",
61 "radio"));
62 usleep(1000);
63 EXPECT_LT(0, __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
64 "TEST__android_log_buf_write",
65 "system"));
66 usleep(1000);
67 EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
68 "TEST__android_log_buf_write",
69 "main"));
70 usleep(1000);
71 }
72
TEST(liblog,__android_log_btwrite)73 TEST(liblog, __android_log_btwrite) {
74 int intBuf = 0xDEADBEEF;
75 EXPECT_LT(0, __android_log_btwrite(0,
76 EVENT_TYPE_INT,
77 &intBuf, sizeof(intBuf)));
78 long long longBuf = 0xDEADBEEFA55A5AA5;
79 EXPECT_LT(0, __android_log_btwrite(0,
80 EVENT_TYPE_LONG,
81 &longBuf, sizeof(longBuf)));
82 usleep(1000);
83 char Buf[] = "\20\0\0\0DeAdBeEfA55a5aA5";
84 EXPECT_LT(0, __android_log_btwrite(0,
85 EVENT_TYPE_STRING,
86 Buf, sizeof(Buf) - 1));
87 usleep(1000);
88 }
89
ConcurrentPrintFn(void * arg)90 static void* ConcurrentPrintFn(void *arg) {
91 int ret = __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
92 "TEST__android_log_print", "Concurrent %" PRIuPTR,
93 reinterpret_cast<uintptr_t>(arg));
94 return reinterpret_cast<void*>(ret);
95 }
96
97 #define NUM_CONCURRENT 64
98 #define _concurrent_name(a,n) a##__concurrent##n
99 #define concurrent_name(a,n) _concurrent_name(a,n)
100
TEST(liblog,concurrent_name (__android_log_buf_print,NUM_CONCURRENT))101 TEST(liblog, concurrent_name(__android_log_buf_print, NUM_CONCURRENT)) {
102 pthread_t t[NUM_CONCURRENT];
103 int i;
104 for (i=0; i < NUM_CONCURRENT; i++) {
105 ASSERT_EQ(0, pthread_create(&t[i], NULL,
106 ConcurrentPrintFn,
107 reinterpret_cast<void *>(i)));
108 }
109 int ret = 0;
110 for (i=0; i < NUM_CONCURRENT; i++) {
111 void* result;
112 ASSERT_EQ(0, pthread_join(t[i], &result));
113 int this_result = reinterpret_cast<uintptr_t>(result);
114 if ((0 == ret) && (0 != this_result)) {
115 ret = this_result;
116 }
117 }
118 ASSERT_LT(0, ret);
119 }
120
TEST(liblog,__android_log_btwrite__android_logger_list_read)121 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
122 struct logger_list *logger_list;
123
124 pid_t pid = getpid();
125
126 ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
127 LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
128
129 log_time ts(CLOCK_MONOTONIC);
130
131 ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
132 usleep(1000000);
133
134 int count = 0;
135
136 for (;;) {
137 log_msg log_msg;
138 if (android_logger_list_read(logger_list, &log_msg) <= 0) {
139 break;
140 }
141
142 ASSERT_EQ(log_msg.entry.pid, pid);
143
144 if ((log_msg.entry.len != (4 + 1 + 8))
145 || (log_msg.id() != LOG_ID_EVENTS)) {
146 continue;
147 }
148
149 char *eventData = log_msg.msg();
150
151 if (eventData[4] != EVENT_TYPE_LONG) {
152 continue;
153 }
154
155 log_time tx(eventData + 4 + 1);
156 if (ts == tx) {
157 ++count;
158 }
159 }
160
161 EXPECT_EQ(1, count);
162
163 android_logger_list_close(logger_list);
164 }
165
166 static unsigned signaled;
167 log_time signal_time;
168
caught_blocking(int)169 static void caught_blocking(int /*signum*/)
170 {
171 unsigned long long v = 0xDEADBEEFA55A0000ULL;
172
173 v += getpid() & 0xFFFF;
174
175 ++signaled;
176 if ((signal_time.tv_sec == 0) && (signal_time.tv_nsec == 0)) {
177 signal_time = log_time(CLOCK_MONOTONIC);
178 signal_time.tv_sec += 2;
179 }
180
181 LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
182 }
183
184 // Fill in current process user and system time in 10ms increments
get_ticks(unsigned long long * uticks,unsigned long long * sticks)185 static void get_ticks(unsigned long long *uticks, unsigned long long *sticks)
186 {
187 *uticks = *sticks = 0;
188
189 pid_t pid = getpid();
190
191 char buffer[512];
192 snprintf(buffer, sizeof(buffer), "/proc/%u/stat", pid);
193
194 FILE *fp = fopen(buffer, "r");
195 if (!fp) {
196 return;
197 }
198
199 char *cp = fgets(buffer, sizeof(buffer), fp);
200 fclose(fp);
201 if (!cp) {
202 return;
203 }
204
205 pid_t d;
206 char s[sizeof(buffer)];
207 char c;
208 long long ll;
209 unsigned long long ull;
210
211 if (15 != sscanf(buffer,
212 "%d %s %c %lld %lld %lld %lld %lld %llu %llu %llu %llu %llu %llu %llu ",
213 &d, s, &c, &ll, &ll, &ll, &ll, &ll, &ull, &ull, &ull, &ull, &ull,
214 uticks, sticks)) {
215 *uticks = *sticks = 0;
216 }
217 }
218
TEST(liblog,android_logger_list_read__cpu)219 TEST(liblog, android_logger_list_read__cpu) {
220 struct logger_list *logger_list;
221 unsigned long long v = 0xDEADBEEFA55A0000ULL;
222
223 pid_t pid = getpid();
224
225 v += pid & 0xFFFF;
226
227 ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
228 LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 1000, pid)));
229
230 int count = 0;
231
232 int signals = 0;
233
234 unsigned long long uticks_start;
235 unsigned long long sticks_start;
236 get_ticks(&uticks_start, &sticks_start);
237
238 const unsigned alarm_time = 10;
239
240 memset(&signal_time, 0, sizeof(signal_time));
241
242 signal(SIGALRM, caught_blocking);
243 alarm(alarm_time);
244
245 signaled = 0;
246
247 do {
248 log_msg log_msg;
249 if (android_logger_list_read(logger_list, &log_msg) <= 0) {
250 break;
251 }
252
253 alarm(alarm_time);
254
255 ++count;
256
257 ASSERT_EQ(log_msg.entry.pid, pid);
258
259 if ((log_msg.entry.len != (4 + 1 + 8))
260 || (log_msg.id() != LOG_ID_EVENTS)) {
261 continue;
262 }
263
264 char *eventData = log_msg.msg();
265
266 if (eventData[4] != EVENT_TYPE_LONG) {
267 continue;
268 }
269
270 unsigned long long l = eventData[4 + 1 + 0] & 0xFF;
271 l |= (unsigned long long) (eventData[4 + 1 + 1] & 0xFF) << 8;
272 l |= (unsigned long long) (eventData[4 + 1 + 2] & 0xFF) << 16;
273 l |= (unsigned long long) (eventData[4 + 1 + 3] & 0xFF) << 24;
274 l |= (unsigned long long) (eventData[4 + 1 + 4] & 0xFF) << 32;
275 l |= (unsigned long long) (eventData[4 + 1 + 5] & 0xFF) << 40;
276 l |= (unsigned long long) (eventData[4 + 1 + 6] & 0xFF) << 48;
277 l |= (unsigned long long) (eventData[4 + 1 + 7] & 0xFF) << 56;
278
279 if (l == v) {
280 ++signals;
281 break;
282 }
283 } while (!signaled || (log_time(CLOCK_MONOTONIC) < signal_time));
284 alarm(0);
285 signal(SIGALRM, SIG_DFL);
286
287 EXPECT_LT(1, count);
288
289 EXPECT_EQ(1, signals);
290
291 android_logger_list_close(logger_list);
292
293 unsigned long long uticks_end;
294 unsigned long long sticks_end;
295 get_ticks(&uticks_end, &sticks_end);
296
297 // Less than 1% in either user or system time, or both
298 const unsigned long long one_percent_ticks = alarm_time;
299 unsigned long long user_ticks = uticks_end - uticks_start;
300 unsigned long long system_ticks = sticks_end - sticks_start;
301 EXPECT_GT(one_percent_ticks, user_ticks);
302 EXPECT_GT(one_percent_ticks, system_ticks);
303 EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
304 }
305
306 static const char max_payload_tag[] = "TEST_max_payload_XXXX";
307 static const char max_payload_buf[LOGGER_ENTRY_MAX_PAYLOAD
308 - sizeof(max_payload_tag) - 1] = "LEONATO\n\
309 I learn in this letter that Don Peter of Arragon\n\
310 comes this night to Messina\n\
311 MESSENGER\n\
312 He is very near by this: he was not three leagues off\n\
313 when I left him\n\
314 LEONATO\n\
315 How many gentlemen have you lost in this action?\n\
316 MESSENGER\n\
317 But few of any sort, and none of name\n\
318 LEONATO\n\
319 A victory is twice itself when the achiever brings\n\
320 home full numbers. I find here that Don Peter hath\n\
321 bestowed much honour on a young Florentine called Claudio\n\
322 MESSENGER\n\
323 Much deserved on his part and equally remembered by\n\
324 Don Pedro: he hath borne himself beyond the\n\
325 promise of his age, doing, in the figure of a lamb,\n\
326 the feats of a lion: he hath indeed better\n\
327 bettered expectation than you must expect of me to\n\
328 tell you how\n\
329 LEONATO\n\
330 He hath an uncle here in Messina will be very much\n\
331 glad of it.\n\
332 MESSENGER\n\
333 I have already delivered him letters, and there\n\
334 appears much joy in him; even so much that joy could\n\
335 not show itself modest enough without a badge of\n\
336 bitterness.\n\
337 LEONATO\n\
338 Did he break out into tears?\n\
339 MESSENGER\n\
340 In great measure.\n\
341 LEONATO\n\
342 A kind overflow of kindness: there are no faces\n\
343 truer than those that are so washed. How much\n\
344 better is it to weep at joy than to joy at weeping!\n\
345 BEATRICE\n\
346 I pray you, is Signior Mountanto returned from the\n\
347 wars or no?\n\
348 MESSENGER\n\
349 I know none of that name, lady: there was none such\n\
350 in the army of any sort.\n\
351 LEONATO\n\
352 What is he that you ask for, niece?\n\
353 HERO\n\
354 My cousin means Signior Benedick of Padua.\n\
355 MESSENGER\n\
356 O, he's returned; and as pleasant as ever he was.\n\
357 BEATRICE\n\
358 He set up his bills here in Messina and challenged\n\
359 Cupid at the flight; and my uncle's fool, reading\n\
360 the challenge, subscribed for Cupid, and challenged\n\
361 him at the bird-bolt. I pray you, how many hath he\n\
362 killed and eaten in these wars? But how many hath\n\
363 he killed? for indeed I promised to eat all of his killing.\n\
364 LEONATO\n\
365 Faith, niece, you tax Signior Benedick too much;\n\
366 but he'll be meet with you, I doubt it not.\n\
367 MESSENGER\n\
368 He hath done good service, lady, in these wars.\n\
369 BEATRICE\n\
370 You had musty victual, and he hath holp to eat it:\n\
371 he is a very valiant trencherman; he hath an\n\
372 excellent stomach.\n\
373 MESSENGER\n\
374 And a good soldier too, lady.\n\
375 BEATRICE\n\
376 And a good soldier to a lady: but what is he to a lord?\n\
377 MESSENGER\n\
378 A lord to a lord, a man to a man; stuffed with all\n\
379 honourable virtues.\n\
380 BEATRICE\n\
381 It is so, indeed; he is no less than a stuffed man:\n\
382 but for the stuffing,--well, we are all mortal.\n\
383 LEONATO\n\
384 You must not, sir, mistake my niece. There is a\n\
385 kind of merry war betwixt Signior Benedick and her:\n\
386 they never meet but there's a skirmish of wit\n\
387 between them.\n\
388 BEATRICE\n\
389 Alas! he gets nothing by that. In our last\n\
390 conflict four of his five wits went halting off, and\n\
391 now is the whole man governed with one: so that if\n\
392 he have wit enough to keep himself warm, let him\n\
393 bear it for a difference between himself and his\n\
394 horse; for it is all the wealth that he hath left,\n\
395 to be known a reasonable creature. Who is his\n\
396 companion now? He hath every month a new sworn brother.\n\
397 MESSENGER\n\
398 Is't possible?\n\
399 BEATRICE\n\
400 Very easily possible: he wears his faith but as\n\
401 the fashion of his hat; it ever changes with the\n\
402 next block.\n\
403 MESSENGER\n\
404 I see, lady, the gentleman is not in your books.\n\
405 BEATRICE\n\
406 No; an he were, I would burn my study. But, I pray\n\
407 you, who is his companion? Is there no young\n\
408 squarer now that will make a voyage with him to the devil?\n\
409 MESSENGER\n\
410 He is most in the company of the right noble Claudio.\n\
411 BEATRICE\n\
412 O Lord, he will hang upon him like a disease: he\n\
413 is sooner caught than the pestilence, and the taker\n\
414 runs presently mad. God help the noble Claudio! if\n\
415 he have caught the Benedick, it will cost him a\n\
416 thousand pound ere a' be cured.\n\
417 MESSENGER\n\
418 I will hold friends with you, lady.\n\
419 BEATRICE\n\
420 Do, good friend.\n\
421 LEONATO\n\
422 You will never run mad, niece.\n\
423 BEATRICE\n\
424 No, not till a hot January.\n\
425 MESSENGER\n\
426 Don Pedro is approached.\n\
427 Enter DON PEDRO, DON JOHN, CLAUDIO, BENEDICK, and BALTHASAR\n\
428 \n\
429 DON PEDRO\n\
430 Good Signior Leonato, you are come to meet your\n\
431 trouble: the fashion of the world is to avoid\n\
432 cost, and you encounter it\n\
433 LEONATO\n\
434 Never came trouble to my house in the likeness";
435
TEST(liblog,max_payload)436 TEST(liblog, max_payload) {
437 pid_t pid = getpid();
438 char tag[sizeof(max_payload_tag)];
439 memcpy(tag, max_payload_tag, sizeof(tag));
440 snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
441
442 LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
443 tag, max_payload_buf));
444 sleep(2);
445
446 struct logger_list *logger_list;
447
448 ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
449 LOG_ID_SYSTEM, ANDROID_LOG_RDONLY, 100, 0)));
450
451 bool matches = false;
452 ssize_t max_len = 0;
453
454 for(;;) {
455 log_msg log_msg;
456 if (android_logger_list_read(logger_list, &log_msg) <= 0) {
457 break;
458 }
459
460 if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
461 continue;
462 }
463
464 char *data = log_msg.msg() + 1;
465
466 if (strcmp(data, tag)) {
467 continue;
468 }
469
470 data += strlen(data) + 1;
471
472 const char *left = data;
473 const char *right = max_payload_buf;
474 while (*left && *right && (*left == *right)) {
475 ++left;
476 ++right;
477 }
478
479 if (max_len <= (left - data)) {
480 max_len = left - data + 1;
481 }
482
483 if (max_len > 512) {
484 matches = true;
485 break;
486 }
487 }
488
489 android_logger_list_close(logger_list);
490
491 EXPECT_EQ(true, matches);
492
493 EXPECT_LE(sizeof(max_payload_buf), static_cast<size_t>(max_len));
494 }
495
TEST(liblog,too_big_payload)496 TEST(liblog, too_big_payload) {
497 pid_t pid = getpid();
498 static const char big_payload_tag[] = "TEST_big_payload_XXXX";
499 char tag[sizeof(big_payload_tag)];
500 memcpy(tag, big_payload_tag, sizeof(tag));
501 snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
502
503 std::string longString(3266519, 'x');
504
505 ssize_t ret = LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM,
506 ANDROID_LOG_INFO, tag, longString.c_str()));
507
508 struct logger_list *logger_list;
509
510 ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
511 LOG_ID_SYSTEM, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 100, 0)));
512
513 ssize_t max_len = 0;
514
515 for(;;) {
516 log_msg log_msg;
517 if (android_logger_list_read(logger_list, &log_msg) <= 0) {
518 break;
519 }
520
521 if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
522 continue;
523 }
524
525 char *data = log_msg.msg() + 1;
526
527 if (strcmp(data, tag)) {
528 continue;
529 }
530
531 data += strlen(data) + 1;
532
533 const char *left = data;
534 const char *right = longString.c_str();
535 while (*left && *right && (*left == *right)) {
536 ++left;
537 ++right;
538 }
539
540 if (max_len <= (left - data)) {
541 max_len = left - data + 1;
542 }
543 }
544
545 android_logger_list_close(logger_list);
546
547 EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
548 static_cast<size_t>(max_len));
549
550 EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
551 }
552
TEST(liblog,dual_reader)553 TEST(liblog, dual_reader) {
554 struct logger_list *logger_list1;
555
556 // >25 messages due to liblog.__android_log_buf_print__concurrentXX above.
557 ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
558 LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 25, 0)));
559
560 struct logger_list *logger_list2;
561
562 if (NULL == (logger_list2 = android_logger_list_open(
563 LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 15, 0))) {
564 android_logger_list_close(logger_list1);
565 ASSERT_TRUE(NULL != logger_list2);
566 }
567
568 int count1 = 0;
569 bool done1 = false;
570 int count2 = 0;
571 bool done2 = false;
572
573 do {
574 log_msg log_msg;
575
576 if (!done1) {
577 if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
578 done1 = true;
579 } else {
580 ++count1;
581 }
582 }
583
584 if (!done2) {
585 if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
586 done2 = true;
587 } else {
588 ++count2;
589 }
590 }
591 } while ((!done1) || (!done2));
592
593 android_logger_list_close(logger_list1);
594 android_logger_list_close(logger_list2);
595
596 EXPECT_EQ(25, count1);
597 EXPECT_EQ(15, count2);
598 }
599
TEST(liblog,android_logger_get_)600 TEST(liblog, android_logger_get_) {
601 struct logger_list * logger_list = android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
602
603 for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
604 log_id_t id = static_cast<log_id_t>(i);
605 const char *name = android_log_id_to_name(id);
606 if (id != android_name_to_log_id(name)) {
607 continue;
608 }
609 fprintf(stderr, "log buffer %s\r", name);
610 struct logger * logger;
611 EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
612 EXPECT_EQ(id, android_logger_get_id(logger));
613 /* crash buffer is allowed to be empty, that is actually healthy! */
614 if (android_logger_get_log_size(logger) || strcmp("crash", name)) {
615 EXPECT_LT(0, android_logger_get_log_size(logger));
616 }
617 EXPECT_LT(0, android_logger_get_log_readable_size(logger));
618 EXPECT_LT(0, android_logger_get_log_version(logger));
619 }
620
621 android_logger_list_close(logger_list);
622 }
623
checkPriForTag(AndroidLogFormat * p_format,const char * tag,android_LogPriority pri)624 static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) {
625 return android_log_shouldPrintLine(p_format, tag, pri)
626 && !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1));
627 }
628
TEST(liblog,filterRule)629 TEST(liblog, filterRule) {
630 static const char tag[] = "random";
631
632 AndroidLogFormat *p_format = android_log_format_new();
633
634 android_log_addFilterRule(p_format,"*:i");
635
636 EXPECT_TRUE(checkPriForTag(p_format, tag, ANDROID_LOG_INFO));
637 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
638 android_log_addFilterRule(p_format, "*");
639 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_DEBUG));
640 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
641 android_log_addFilterRule(p_format, "*:v");
642 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_VERBOSE));
643 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
644 android_log_addFilterRule(p_format, "*:i");
645 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_INFO));
646 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
647
648 android_log_addFilterRule(p_format, tag);
649 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_VERBOSE));
650 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
651 android_log_addFilterRule(p_format, "random:v");
652 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_VERBOSE));
653 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
654 android_log_addFilterRule(p_format, "random:d");
655 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_DEBUG));
656 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
657 android_log_addFilterRule(p_format, "random:w");
658 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_WARN));
659 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
660
661 android_log_addFilterRule(p_format, "crap:*");
662 EXPECT_TRUE (checkPriForTag(p_format, "crap", ANDROID_LOG_VERBOSE));
663 EXPECT_TRUE(android_log_shouldPrintLine(p_format, "crap", ANDROID_LOG_VERBOSE) > 0);
664
665 // invalid expression
666 EXPECT_TRUE (android_log_addFilterRule(p_format, "random:z") < 0);
667 EXPECT_TRUE (checkPriForTag(p_format, tag, ANDROID_LOG_WARN));
668 EXPECT_TRUE(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
669
670 // Issue #550946
671 EXPECT_TRUE(android_log_addFilterString(p_format, " ") == 0);
672 EXPECT_TRUE(checkPriForTag(p_format, tag, ANDROID_LOG_WARN));
673
674 // note trailing space
675 EXPECT_TRUE(android_log_addFilterString(p_format, "*:s random:d ") == 0);
676 EXPECT_TRUE(checkPriForTag(p_format, tag, ANDROID_LOG_DEBUG));
677
678 EXPECT_TRUE(android_log_addFilterString(p_format, "*:s random:z") < 0);
679
680 #if 0 // bitrot, seek update
681 char defaultBuffer[512];
682
683 android_log_formatLogLine(p_format,
684 defaultBuffer, sizeof(defaultBuffer), 0, ANDROID_LOG_ERROR, 123,
685 123, 123, tag, "nofile", strlen("Hello"), "Hello", NULL);
686
687 fprintf(stderr, "%s\n", defaultBuffer);
688 #endif
689
690 android_log_format_free(p_format);
691 }
692
TEST(liblog,is_loggable)693 TEST(liblog, is_loggable) {
694 static const char tag[] = "is_loggable";
695 static const char log_namespace[] = "persist.log.tag.";
696 static const size_t base_offset = 8; /* skip "persist." */
697 // sizeof("string") = strlen("string") + 1
698 char key[sizeof(log_namespace) + sizeof(tag) - 1];
699 char hold[4][PROP_VALUE_MAX];
700 static const struct {
701 int level;
702 char type;
703 } levels[] = {
704 { ANDROID_LOG_VERBOSE, 'v' },
705 { ANDROID_LOG_DEBUG , 'd' },
706 { ANDROID_LOG_INFO , 'i' },
707 { ANDROID_LOG_WARN , 'w' },
708 { ANDROID_LOG_ERROR , 'e' },
709 { ANDROID_LOG_FATAL , 'a' },
710 { -1 , 's' },
711 { -2 , 'g' }, // Illegal value, resort to default
712 };
713
714 // Set up initial test condition
715 memset(hold, 0, sizeof(hold));
716 snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
717 property_get(key, hold[0], "");
718 property_set(key, "");
719 property_get(key + base_offset, hold[1], "");
720 property_set(key + base_offset, "");
721 strcpy(key, log_namespace);
722 key[sizeof(log_namespace) - 2] = '\0';
723 property_get(key, hold[2], "");
724 property_set(key, "");
725 property_get(key, hold[3], "");
726 property_set(key + base_offset, "");
727
728 // All combinations of level and defaults
729 for(size_t i = 0; i < (sizeof(levels) / sizeof(levels[0])); ++i) {
730 if (levels[i].level == -2) {
731 continue;
732 }
733 for(size_t j = 0; j < (sizeof(levels) / sizeof(levels[0])); ++j) {
734 if (levels[j].level == -2) {
735 continue;
736 }
737 fprintf(stderr, "i=%zu j=%zu\r", i, j);
738 if ((levels[i].level < levels[j].level)
739 || (levels[j].level == -1)) {
740 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
741 levels[j].level));
742 } else {
743 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
744 levels[j].level));
745 }
746 }
747 }
748
749 // All combinations of level and tag and global properties
750 for(size_t i = 0; i < (sizeof(levels) / sizeof(levels[0])); ++i) {
751 if (levels[i].level == -2) {
752 continue;
753 }
754 for(size_t j = 0; j < (sizeof(levels) / sizeof(levels[0])); ++j) {
755 char buf[2];
756 buf[0] = levels[j].type;
757 buf[1] = '\0';
758
759 snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
760 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
761 i, j, key, buf);
762 property_set(key, buf);
763 if ((levels[i].level < levels[j].level)
764 || (levels[j].level == -1)
765 || ((levels[i].level < ANDROID_LOG_DEBUG)
766 && (levels[j].level == -2))) {
767 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
768 ANDROID_LOG_DEBUG));
769 } else {
770 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
771 ANDROID_LOG_DEBUG));
772 }
773 property_set(key, "");
774
775 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
776 i, j, key + base_offset, buf);
777 property_set(key + base_offset, buf);
778 if ((levels[i].level < levels[j].level)
779 || (levels[j].level == -1)
780 || ((levels[i].level < ANDROID_LOG_DEBUG)
781 && (levels[j].level == -2))) {
782 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
783 ANDROID_LOG_DEBUG));
784 } else {
785 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
786 ANDROID_LOG_DEBUG));
787 }
788 property_set(key + base_offset, "");
789
790 strcpy(key, log_namespace);
791 key[sizeof(log_namespace) - 2] = '\0';
792 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
793 i, j, key, buf);
794 property_set(key, buf);
795 if ((levels[i].level < levels[j].level)
796 || (levels[j].level == -1)
797 || ((levels[i].level < ANDROID_LOG_DEBUG)
798 && (levels[j].level == -2))) {
799 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
800 ANDROID_LOG_DEBUG));
801 } else {
802 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
803 ANDROID_LOG_DEBUG));
804 }
805 property_set(key, "");
806
807 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
808 i, j, key + base_offset, buf);
809 property_set(key + base_offset, buf);
810 if ((levels[i].level < levels[j].level)
811 || (levels[j].level == -1)
812 || ((levels[i].level < ANDROID_LOG_DEBUG)
813 && (levels[j].level == -2))) {
814 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
815 ANDROID_LOG_DEBUG));
816 } else {
817 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
818 ANDROID_LOG_DEBUG));
819 }
820 property_set(key + base_offset, "");
821 }
822 }
823
824 // All combinations of level and tag properties, but with global set to INFO
825 strcpy(key, log_namespace);
826 key[sizeof(log_namespace) - 2] = '\0';
827 property_set(key, "I");
828 snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
829 for(size_t i = 0; i < (sizeof(levels) / sizeof(levels[0])); ++i) {
830 if (levels[i].level == -2) {
831 continue;
832 }
833 for(size_t j = 0; j < (sizeof(levels) / sizeof(levels[0])); ++j) {
834 char buf[2];
835 buf[0] = levels[j].type;
836 buf[1] = '\0';
837
838 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
839 i, j, key, buf);
840 property_set(key, buf);
841 if ((levels[i].level < levels[j].level)
842 || (levels[j].level == -1)
843 || ((levels[i].level < ANDROID_LOG_INFO) // Yes INFO
844 && (levels[j].level == -2))) {
845 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
846 ANDROID_LOG_DEBUG));
847 } else {
848 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
849 ANDROID_LOG_DEBUG));
850 }
851 property_set(key, "");
852
853 fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
854 i, j, key + base_offset, buf);
855 property_set(key + base_offset, buf);
856 if ((levels[i].level < levels[j].level)
857 || (levels[j].level == -1)
858 || ((levels[i].level < ANDROID_LOG_INFO) // Yes INFO
859 && (levels[j].level == -2))) {
860 EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
861 ANDROID_LOG_DEBUG));
862 } else {
863 EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
864 ANDROID_LOG_DEBUG));
865 }
866 property_set(key + base_offset, "");
867 }
868 }
869
870 // reset parms
871 snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
872 property_set(key, hold[0]);
873 property_set(key + base_offset, hold[1]);
874 strcpy(key, log_namespace);
875 key[sizeof(log_namespace) - 2] = '\0';
876 property_set(key, hold[2]);
877 property_set(key + base_offset, hold[3]);
878 }
879