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