xref: /aosp_15_r20/system/logging/logcat/tests/logcat_test.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2013-2014 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker  *
4*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker  *
8*598139dcSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker  *
10*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker  */
16*598139dcSAndroid Build Coastguard Worker 
17*598139dcSAndroid Build Coastguard Worker #define _POSIX_THREAD_SAFE_FUNCTIONS  // For mingw localtime_r().
18*598139dcSAndroid Build Coastguard Worker 
19*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
20*598139dcSAndroid Build Coastguard Worker #include <dirent.h>
21*598139dcSAndroid Build Coastguard Worker #include <pwd.h>
22*598139dcSAndroid Build Coastguard Worker #include <signal.h>
23*598139dcSAndroid Build Coastguard Worker #include <stdint.h>
24*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
25*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
26*598139dcSAndroid Build Coastguard Worker #include <string.h>
27*598139dcSAndroid Build Coastguard Worker #include <sys/cdefs.h>
28*598139dcSAndroid Build Coastguard Worker #include <sys/stat.h>
29*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
30*598139dcSAndroid Build Coastguard Worker #include <sys/wait.h>
31*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
32*598139dcSAndroid Build Coastguard Worker 
33*598139dcSAndroid Build Coastguard Worker #include <memory>
34*598139dcSAndroid Build Coastguard Worker #include <regex>
35*598139dcSAndroid Build Coastguard Worker #include <string>
36*598139dcSAndroid Build Coastguard Worker 
37*598139dcSAndroid Build Coastguard Worker #include <android-base/file.h>
38*598139dcSAndroid Build Coastguard Worker #include <android-base/macros.h>
39*598139dcSAndroid Build Coastguard Worker #include <android-base/parseint.h>
40*598139dcSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
41*598139dcSAndroid Build Coastguard Worker #include <android-base/strings.h>
42*598139dcSAndroid Build Coastguard Worker #include <gtest/gtest.h>
43*598139dcSAndroid Build Coastguard Worker #include <log/event_tag_map.h>
44*598139dcSAndroid Build Coastguard Worker #include <log/log.h>
45*598139dcSAndroid Build Coastguard Worker #include <log/log_event_list.h>
46*598139dcSAndroid Build Coastguard Worker 
47*598139dcSAndroid Build Coastguard Worker #ifndef logcat_executable
48*598139dcSAndroid Build Coastguard Worker #define USING_LOGCAT_EXECUTABLE_DEFAULT
49*598139dcSAndroid Build Coastguard Worker #define logcat_executable "logcat"
50*598139dcSAndroid Build Coastguard Worker #endif
51*598139dcSAndroid Build Coastguard Worker 
52*598139dcSAndroid Build Coastguard Worker #define BIG_BUFFER (5 * 1024)
53*598139dcSAndroid Build Coastguard Worker 
54*598139dcSAndroid Build Coastguard Worker // rest(), let the logs settle.
55*598139dcSAndroid Build Coastguard Worker //
56*598139dcSAndroid Build Coastguard Worker // logd is in a background cgroup and under extreme load can take up to
57*598139dcSAndroid Build Coastguard Worker // 3 seconds to land a log entry. Under moderate load we can do with 200ms.
rest()58*598139dcSAndroid Build Coastguard Worker static void rest() {
59*598139dcSAndroid Build Coastguard Worker     static const useconds_t restPeriod = 200000;
60*598139dcSAndroid Build Coastguard Worker 
61*598139dcSAndroid Build Coastguard Worker     usleep(restPeriod);
62*598139dcSAndroid Build Coastguard Worker }
63*598139dcSAndroid Build Coastguard Worker 
64*598139dcSAndroid Build Coastguard Worker // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
65*598139dcSAndroid Build Coastguard Worker // non-syscall libs. Since we are only using this in the emergency of
66*598139dcSAndroid Build Coastguard Worker // a signal to stuff a terminating code into the logs, we will spin rather
67*598139dcSAndroid Build Coastguard Worker // than try a usleep.
68*598139dcSAndroid Build Coastguard Worker #define LOG_FAILURE_RETRY(exp)                                               \
69*598139dcSAndroid Build Coastguard Worker     ({                                                                       \
70*598139dcSAndroid Build Coastguard Worker         typeof(exp) _rc;                                                     \
71*598139dcSAndroid Build Coastguard Worker         do {                                                                 \
72*598139dcSAndroid Build Coastguard Worker             _rc = (exp);                                                     \
73*598139dcSAndroid Build Coastguard Worker         } while (((_rc == -1) && ((errno == EINTR) || (errno == EAGAIN))) || \
74*598139dcSAndroid Build Coastguard Worker                  (_rc == -EINTR) || (_rc == -EAGAIN));                       \
75*598139dcSAndroid Build Coastguard Worker         _rc;                                                                 \
76*598139dcSAndroid Build Coastguard Worker     })
77*598139dcSAndroid Build Coastguard Worker 
78*598139dcSAndroid Build Coastguard Worker static const char begin[] = "--------- beginning of ";
79*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,buckets)80*598139dcSAndroid Build Coastguard Worker TEST(logcat, buckets) {
81*598139dcSAndroid Build Coastguard Worker     FILE* fp;
82*598139dcSAndroid Build Coastguard Worker 
83*598139dcSAndroid Build Coastguard Worker #undef LOG_TAG
84*598139dcSAndroid Build Coastguard Worker #define LOG_TAG "inject.buckets"
85*598139dcSAndroid Build Coastguard Worker     // inject messages into radio, system, main and events buffers to
86*598139dcSAndroid Build Coastguard Worker     // ensure that we see all the begin[] bucket messages.
87*598139dcSAndroid Build Coastguard Worker     RLOGE(logcat_executable);
88*598139dcSAndroid Build Coastguard Worker     SLOGE(logcat_executable);
89*598139dcSAndroid Build Coastguard Worker     ALOGE(logcat_executable);
90*598139dcSAndroid Build Coastguard Worker     __android_log_bswrite(0, logcat_executable ".inject.buckets");
91*598139dcSAndroid Build Coastguard Worker     rest();
92*598139dcSAndroid Build Coastguard Worker 
93*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != (fp = popen(logcat_executable
94*598139dcSAndroid Build Coastguard Worker                                     " -b radio -b events -b system -b main -d 2>/dev/null",
95*598139dcSAndroid Build Coastguard Worker                                     "r")));
96*598139dcSAndroid Build Coastguard Worker 
97*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
98*598139dcSAndroid Build Coastguard Worker 
99*598139dcSAndroid Build Coastguard Worker     int ids = 0;
100*598139dcSAndroid Build Coastguard Worker     int count = 0;
101*598139dcSAndroid Build Coastguard Worker 
102*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
103*598139dcSAndroid Build Coastguard Worker         if (!strncmp(begin, buffer, sizeof(begin) - 1)) {
104*598139dcSAndroid Build Coastguard Worker             while (char* cp = strrchr(buffer, '\n')) {
105*598139dcSAndroid Build Coastguard Worker                 *cp = '\0';
106*598139dcSAndroid Build Coastguard Worker             }
107*598139dcSAndroid Build Coastguard Worker             log_id_t id = android_name_to_log_id(buffer + sizeof(begin) - 1);
108*598139dcSAndroid Build Coastguard Worker             ids |= 1 << id;
109*598139dcSAndroid Build Coastguard Worker             ++count;
110*598139dcSAndroid Build Coastguard Worker         }
111*598139dcSAndroid Build Coastguard Worker     }
112*598139dcSAndroid Build Coastguard Worker 
113*598139dcSAndroid Build Coastguard Worker     pclose(fp);
114*598139dcSAndroid Build Coastguard Worker 
115*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(ids, 15);
116*598139dcSAndroid Build Coastguard Worker 
117*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(count, 4);
118*598139dcSAndroid Build Coastguard Worker }
119*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,event_tag_filter)120*598139dcSAndroid Build Coastguard Worker TEST(logcat, event_tag_filter) {
121*598139dcSAndroid Build Coastguard Worker     FILE* fp;
122*598139dcSAndroid Build Coastguard Worker 
123*598139dcSAndroid Build Coastguard Worker #undef LOG_TAG
124*598139dcSAndroid Build Coastguard Worker #define LOG_TAG "inject.filter"
125*598139dcSAndroid Build Coastguard Worker     // inject messages into radio, system and main buffers
126*598139dcSAndroid Build Coastguard Worker     // with our unique log tag to test logcat filter.
127*598139dcSAndroid Build Coastguard Worker     RLOGE(logcat_executable);
128*598139dcSAndroid Build Coastguard Worker     SLOGE(logcat_executable);
129*598139dcSAndroid Build Coastguard Worker     ALOGE(logcat_executable);
130*598139dcSAndroid Build Coastguard Worker     rest();
131*598139dcSAndroid Build Coastguard Worker 
132*598139dcSAndroid Build Coastguard Worker     std::string command = android::base::StringPrintf(
133*598139dcSAndroid Build Coastguard Worker         logcat_executable
134*598139dcSAndroid Build Coastguard Worker         " -b radio -b system -b main --pid=%d -d -s inject.filter 2>/dev/null",
135*598139dcSAndroid Build Coastguard Worker         getpid());
136*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != (fp = popen(command.c_str(), "r")));
137*598139dcSAndroid Build Coastguard Worker 
138*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
139*598139dcSAndroid Build Coastguard Worker 
140*598139dcSAndroid Build Coastguard Worker     int count = 0;
141*598139dcSAndroid Build Coastguard Worker 
142*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
143*598139dcSAndroid Build Coastguard Worker         if (strncmp(begin, buffer, sizeof(begin) - 1)) ++count;
144*598139dcSAndroid Build Coastguard Worker     }
145*598139dcSAndroid Build Coastguard Worker 
146*598139dcSAndroid Build Coastguard Worker     pclose(fp);
147*598139dcSAndroid Build Coastguard Worker 
148*598139dcSAndroid Build Coastguard Worker     // logcat and logcatd test instances result in the progression
149*598139dcSAndroid Build Coastguard Worker     // of 3, 6, and 9 for our counts as each round is performed.
150*598139dcSAndroid Build Coastguard Worker     EXPECT_GE(count, 3);
151*598139dcSAndroid Build Coastguard Worker     EXPECT_LE(count, 9);
152*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(count % 3, 0);
153*598139dcSAndroid Build Coastguard Worker }
154*598139dcSAndroid Build Coastguard Worker 
155*598139dcSAndroid Build Coastguard Worker // If there is not enough background noise in the logs, then spam the logs to
156*598139dcSAndroid Build Coastguard Worker // permit tail checking so that the tests can progress.
inject(ssize_t count)157*598139dcSAndroid Build Coastguard Worker static size_t inject(ssize_t count) {
158*598139dcSAndroid Build Coastguard Worker     if (count <= 0) return 0;
159*598139dcSAndroid Build Coastguard Worker 
160*598139dcSAndroid Build Coastguard Worker     static const size_t retry = 4;
161*598139dcSAndroid Build Coastguard Worker     size_t errors = retry;
162*598139dcSAndroid Build Coastguard Worker     size_t num = 0;
163*598139dcSAndroid Build Coastguard Worker     for (;;) {
164*598139dcSAndroid Build Coastguard Worker         log_time ts(CLOCK_MONOTONIC);
165*598139dcSAndroid Build Coastguard Worker         if (__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) >= 0) {
166*598139dcSAndroid Build Coastguard Worker             if (++num >= (size_t)count) {
167*598139dcSAndroid Build Coastguard Worker                 // let data settle end-to-end
168*598139dcSAndroid Build Coastguard Worker                 sleep(3);
169*598139dcSAndroid Build Coastguard Worker                 return num;
170*598139dcSAndroid Build Coastguard Worker             }
171*598139dcSAndroid Build Coastguard Worker             errors = retry;
172*598139dcSAndroid Build Coastguard Worker             usleep(100);  // ~32 per timer tick, we are a spammer regardless
173*598139dcSAndroid Build Coastguard Worker         } else if (--errors <= 0) {
174*598139dcSAndroid Build Coastguard Worker             return num;
175*598139dcSAndroid Build Coastguard Worker         }
176*598139dcSAndroid Build Coastguard Worker     }
177*598139dcSAndroid Build Coastguard Worker     // NOTREACH
178*598139dcSAndroid Build Coastguard Worker     return num;
179*598139dcSAndroid Build Coastguard Worker }
180*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,year)181*598139dcSAndroid Build Coastguard Worker TEST(logcat, year) {
182*598139dcSAndroid Build Coastguard Worker     int count;
183*598139dcSAndroid Build Coastguard Worker     int tries = 3;  // in case run too soon after system start or buffer clear
184*598139dcSAndroid Build Coastguard Worker 
185*598139dcSAndroid Build Coastguard Worker     do {
186*598139dcSAndroid Build Coastguard Worker         FILE* fp;
187*598139dcSAndroid Build Coastguard Worker 
188*598139dcSAndroid Build Coastguard Worker         char needle[32];
189*598139dcSAndroid Build Coastguard Worker         time_t now;
190*598139dcSAndroid Build Coastguard Worker         time(&now);
191*598139dcSAndroid Build Coastguard Worker         struct tm tmBuf;
192*598139dcSAndroid Build Coastguard Worker         struct tm* ptm = localtime_r(&now, &tmBuf);
193*598139dcSAndroid Build Coastguard Worker         strftime(needle, sizeof(needle), "[ %Y-", ptm);
194*598139dcSAndroid Build Coastguard Worker 
195*598139dcSAndroid Build Coastguard Worker         ASSERT_TRUE(NULL !=
196*598139dcSAndroid Build Coastguard Worker                     (fp = popen(logcat_executable " -v long -v year -b all -t 3 2>/dev/null", "r")));
197*598139dcSAndroid Build Coastguard Worker 
198*598139dcSAndroid Build Coastguard Worker         char buffer[BIG_BUFFER];
199*598139dcSAndroid Build Coastguard Worker 
200*598139dcSAndroid Build Coastguard Worker         count = 0;
201*598139dcSAndroid Build Coastguard Worker 
202*598139dcSAndroid Build Coastguard Worker         while (fgets(buffer, sizeof(buffer), fp)) {
203*598139dcSAndroid Build Coastguard Worker             if (!strncmp(buffer, needle, strlen(needle))) {
204*598139dcSAndroid Build Coastguard Worker                 ++count;
205*598139dcSAndroid Build Coastguard Worker             }
206*598139dcSAndroid Build Coastguard Worker         }
207*598139dcSAndroid Build Coastguard Worker         pclose(fp);
208*598139dcSAndroid Build Coastguard Worker 
209*598139dcSAndroid Build Coastguard Worker     } while ((count < 3) && --tries && inject(3 - count));
210*598139dcSAndroid Build Coastguard Worker 
211*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(3, count);
212*598139dcSAndroid Build Coastguard Worker }
213*598139dcSAndroid Build Coastguard Worker 
214*598139dcSAndroid Build Coastguard Worker // Return a pointer to each null terminated -v long time field.
fgetLongTime(char * buffer,size_t buflen,FILE * fp)215*598139dcSAndroid Build Coastguard Worker static char* fgetLongTime(char* buffer, size_t buflen, FILE* fp) {
216*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, buflen, fp)) {
217*598139dcSAndroid Build Coastguard Worker         char* cp = buffer;
218*598139dcSAndroid Build Coastguard Worker         if (*cp != '[') {
219*598139dcSAndroid Build Coastguard Worker             continue;
220*598139dcSAndroid Build Coastguard Worker         }
221*598139dcSAndroid Build Coastguard Worker         while (*++cp == ' ') {
222*598139dcSAndroid Build Coastguard Worker             ;
223*598139dcSAndroid Build Coastguard Worker         }
224*598139dcSAndroid Build Coastguard Worker         char* ep = cp;
225*598139dcSAndroid Build Coastguard Worker         while (isdigit(*ep)) {
226*598139dcSAndroid Build Coastguard Worker             ++ep;
227*598139dcSAndroid Build Coastguard Worker         }
228*598139dcSAndroid Build Coastguard Worker         if ((*ep != '-') && (*ep != '.')) {
229*598139dcSAndroid Build Coastguard Worker             continue;
230*598139dcSAndroid Build Coastguard Worker         }
231*598139dcSAndroid Build Coastguard Worker         // Find PID field.  Look for ': ' or ':[0-9][0-9][0-9]'
232*598139dcSAndroid Build Coastguard Worker         while (((ep = strchr(ep, ':'))) && (*++ep != ' ')) {
233*598139dcSAndroid Build Coastguard Worker             if (isdigit(ep[0]) && isdigit(ep[1]) && isdigit(ep[2])) break;
234*598139dcSAndroid Build Coastguard Worker         }
235*598139dcSAndroid Build Coastguard Worker         if (!ep) {
236*598139dcSAndroid Build Coastguard Worker             continue;
237*598139dcSAndroid Build Coastguard Worker         }
238*598139dcSAndroid Build Coastguard Worker         static const size_t pid_field_width = 7;
239*598139dcSAndroid Build Coastguard Worker         ep -= pid_field_width;
240*598139dcSAndroid Build Coastguard Worker         *ep = '\0';
241*598139dcSAndroid Build Coastguard Worker         return cp;
242*598139dcSAndroid Build Coastguard Worker     }
243*598139dcSAndroid Build Coastguard Worker     return NULL;
244*598139dcSAndroid Build Coastguard Worker }
245*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tz)246*598139dcSAndroid Build Coastguard Worker TEST(logcat, tz) {
247*598139dcSAndroid Build Coastguard Worker     int tries = 4;  // in case run too soon after system start or buffer clear
248*598139dcSAndroid Build Coastguard Worker     int count;
249*598139dcSAndroid Build Coastguard Worker 
250*598139dcSAndroid Build Coastguard Worker     do {
251*598139dcSAndroid Build Coastguard Worker         FILE* fp;
252*598139dcSAndroid Build Coastguard Worker 
253*598139dcSAndroid Build Coastguard Worker         ASSERT_TRUE(NULL != (fp = popen(logcat_executable
254*598139dcSAndroid Build Coastguard Worker                                         " -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
255*598139dcSAndroid Build Coastguard Worker                                         "r")));
256*598139dcSAndroid Build Coastguard Worker 
257*598139dcSAndroid Build Coastguard Worker         char buffer[BIG_BUFFER];
258*598139dcSAndroid Build Coastguard Worker 
259*598139dcSAndroid Build Coastguard Worker         count = 0;
260*598139dcSAndroid Build Coastguard Worker 
261*598139dcSAndroid Build Coastguard Worker         while (fgetLongTime(buffer, sizeof(buffer), fp)) {
262*598139dcSAndroid Build Coastguard Worker             if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
263*598139dcSAndroid Build Coastguard Worker                 ++count;
264*598139dcSAndroid Build Coastguard Worker             } else {
265*598139dcSAndroid Build Coastguard Worker                 fprintf(stderr, "ts=\"%s\"\n", buffer + 2);
266*598139dcSAndroid Build Coastguard Worker             }
267*598139dcSAndroid Build Coastguard Worker         }
268*598139dcSAndroid Build Coastguard Worker 
269*598139dcSAndroid Build Coastguard Worker         pclose(fp);
270*598139dcSAndroid Build Coastguard Worker 
271*598139dcSAndroid Build Coastguard Worker     } while ((count < 3) && --tries && inject(3 - count));
272*598139dcSAndroid Build Coastguard Worker 
273*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(3, count);
274*598139dcSAndroid Build Coastguard Worker }
275*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,ntz)276*598139dcSAndroid Build Coastguard Worker TEST(logcat, ntz) {
277*598139dcSAndroid Build Coastguard Worker     FILE* fp;
278*598139dcSAndroid Build Coastguard Worker 
279*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL !=
280*598139dcSAndroid Build Coastguard Worker                 (fp = popen(logcat_executable
281*598139dcSAndroid Build Coastguard Worker                             " -v long -v America/Los_Angeles -v zone -b all -t 3 2>/dev/null",
282*598139dcSAndroid Build Coastguard Worker                             "r")));
283*598139dcSAndroid Build Coastguard Worker 
284*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
285*598139dcSAndroid Build Coastguard Worker 
286*598139dcSAndroid Build Coastguard Worker     int count = 0;
287*598139dcSAndroid Build Coastguard Worker 
288*598139dcSAndroid Build Coastguard Worker     while (fgetLongTime(buffer, sizeof(buffer), fp)) {
289*598139dcSAndroid Build Coastguard Worker         if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
290*598139dcSAndroid Build Coastguard Worker             ++count;
291*598139dcSAndroid Build Coastguard Worker         }
292*598139dcSAndroid Build Coastguard Worker     }
293*598139dcSAndroid Build Coastguard Worker 
294*598139dcSAndroid Build Coastguard Worker     pclose(fp);
295*598139dcSAndroid Build Coastguard Worker 
296*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(0, count);
297*598139dcSAndroid Build Coastguard Worker }
298*598139dcSAndroid Build Coastguard Worker 
do_tail(int num)299*598139dcSAndroid Build Coastguard Worker static void do_tail(int num) {
300*598139dcSAndroid Build Coastguard Worker     int tries = 4;  // in case run too soon after system start or buffer clear
301*598139dcSAndroid Build Coastguard Worker     int count;
302*598139dcSAndroid Build Coastguard Worker 
303*598139dcSAndroid Build Coastguard Worker     if (num > 10) ++tries;
304*598139dcSAndroid Build Coastguard Worker     if (num > 100) ++tries;
305*598139dcSAndroid Build Coastguard Worker     do {
306*598139dcSAndroid Build Coastguard Worker         char buffer[BIG_BUFFER];
307*598139dcSAndroid Build Coastguard Worker 
308*598139dcSAndroid Build Coastguard Worker         snprintf(buffer, sizeof(buffer),
309*598139dcSAndroid Build Coastguard Worker                  "ANDROID_PRINTF_LOG=long logcat -b all -t %d 2>/dev/null", num);
310*598139dcSAndroid Build Coastguard Worker 
311*598139dcSAndroid Build Coastguard Worker         FILE* fp;
312*598139dcSAndroid Build Coastguard Worker         ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
313*598139dcSAndroid Build Coastguard Worker 
314*598139dcSAndroid Build Coastguard Worker         count = 0;
315*598139dcSAndroid Build Coastguard Worker 
316*598139dcSAndroid Build Coastguard Worker         while (fgetLongTime(buffer, sizeof(buffer), fp)) {
317*598139dcSAndroid Build Coastguard Worker             ++count;
318*598139dcSAndroid Build Coastguard Worker         }
319*598139dcSAndroid Build Coastguard Worker 
320*598139dcSAndroid Build Coastguard Worker         pclose(fp);
321*598139dcSAndroid Build Coastguard Worker 
322*598139dcSAndroid Build Coastguard Worker     } while ((count < num) && --tries && inject(num - count));
323*598139dcSAndroid Build Coastguard Worker 
324*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(num, count);
325*598139dcSAndroid Build Coastguard Worker }
326*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_3)327*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_3) {
328*598139dcSAndroid Build Coastguard Worker     do_tail(3);
329*598139dcSAndroid Build Coastguard Worker }
330*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_10)331*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_10) {
332*598139dcSAndroid Build Coastguard Worker     do_tail(10);
333*598139dcSAndroid Build Coastguard Worker }
334*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_100)335*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_100) {
336*598139dcSAndroid Build Coastguard Worker     do_tail(100);
337*598139dcSAndroid Build Coastguard Worker }
338*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_1000)339*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_1000) {
340*598139dcSAndroid Build Coastguard Worker     do_tail(1000);
341*598139dcSAndroid Build Coastguard Worker }
342*598139dcSAndroid Build Coastguard Worker 
do_tail_time(const char * cmd)343*598139dcSAndroid Build Coastguard Worker static void do_tail_time(const char* cmd) {
344*598139dcSAndroid Build Coastguard Worker     FILE* fp;
345*598139dcSAndroid Build Coastguard Worker     int count;
346*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
347*598139dcSAndroid Build Coastguard Worker     char* last_timestamp = NULL;
348*598139dcSAndroid Build Coastguard Worker     // Hard to predict 100% if first (overlap) or second line will match.
349*598139dcSAndroid Build Coastguard Worker     // -v nsec will in a substantial majority be the second line.
350*598139dcSAndroid Build Coastguard Worker     char* first_timestamp = NULL;
351*598139dcSAndroid Build Coastguard Worker     char* second_timestamp = NULL;
352*598139dcSAndroid Build Coastguard Worker     char* input;
353*598139dcSAndroid Build Coastguard Worker 
354*598139dcSAndroid Build Coastguard Worker     int tries = 4;  // in case run too soon after system start or buffer clear
355*598139dcSAndroid Build Coastguard Worker 
356*598139dcSAndroid Build Coastguard Worker     do {
357*598139dcSAndroid Build Coastguard Worker         snprintf(buffer, sizeof(buffer), "%s -t 10 2>&1", cmd);
358*598139dcSAndroid Build Coastguard Worker         ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
359*598139dcSAndroid Build Coastguard Worker         count = 0;
360*598139dcSAndroid Build Coastguard Worker 
361*598139dcSAndroid Build Coastguard Worker         while ((input = fgetLongTime(buffer, sizeof(buffer), fp))) {
362*598139dcSAndroid Build Coastguard Worker             ++count;
363*598139dcSAndroid Build Coastguard Worker             if (!first_timestamp) {
364*598139dcSAndroid Build Coastguard Worker                 first_timestamp = strdup(input);
365*598139dcSAndroid Build Coastguard Worker             } else if (!second_timestamp) {
366*598139dcSAndroid Build Coastguard Worker                 second_timestamp = strdup(input);
367*598139dcSAndroid Build Coastguard Worker             }
368*598139dcSAndroid Build Coastguard Worker             free(last_timestamp);
369*598139dcSAndroid Build Coastguard Worker             last_timestamp = strdup(input);
370*598139dcSAndroid Build Coastguard Worker         }
371*598139dcSAndroid Build Coastguard Worker         pclose(fp);
372*598139dcSAndroid Build Coastguard Worker 
373*598139dcSAndroid Build Coastguard Worker     } while ((count < 10) && --tries && inject(10 - count));
374*598139dcSAndroid Build Coastguard Worker 
375*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(count, 10);  // We want _some_ history, too small, falses below
376*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(last_timestamp != NULL);
377*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(first_timestamp != NULL);
378*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(second_timestamp != NULL);
379*598139dcSAndroid Build Coastguard Worker 
380*598139dcSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer), "%s -t '%s' 2>&1", cmd, first_timestamp);
381*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
382*598139dcSAndroid Build Coastguard Worker 
383*598139dcSAndroid Build Coastguard Worker     int second_count = 0;
384*598139dcSAndroid Build Coastguard Worker     int last_timestamp_count = -1;
385*598139dcSAndroid Build Coastguard Worker 
386*598139dcSAndroid Build Coastguard Worker     --count;  // One less unless we match the first_timestamp
387*598139dcSAndroid Build Coastguard Worker     bool found = false;
388*598139dcSAndroid Build Coastguard Worker     while ((input = fgetLongTime(buffer, sizeof(buffer), fp))) {
389*598139dcSAndroid Build Coastguard Worker         ++second_count;
390*598139dcSAndroid Build Coastguard Worker         // We want to highlight if we skip to the next entry.
391*598139dcSAndroid Build Coastguard Worker         // WAI, if the time in logd is *exactly*
392*598139dcSAndroid Build Coastguard Worker         // XX-XX XX:XX:XX.XXXXXX000 (usec) or XX-XX XX:XX:XX.XXX000000
393*598139dcSAndroid Build Coastguard Worker         // this can happen, but it should not happen with nsec.
394*598139dcSAndroid Build Coastguard Worker         // We can make this WAI behavior happen 1000 times less
395*598139dcSAndroid Build Coastguard Worker         // frequently if the caller does not use the -v usec flag,
396*598139dcSAndroid Build Coastguard Worker         // but always the second (always skip) if they use the
397*598139dcSAndroid Build Coastguard Worker         // (undocumented) -v nsec flag.
398*598139dcSAndroid Build Coastguard Worker         if (first_timestamp) {
399*598139dcSAndroid Build Coastguard Worker             found = !strcmp(input, first_timestamp);
400*598139dcSAndroid Build Coastguard Worker             if (found) {
401*598139dcSAndroid Build Coastguard Worker                 ++count;
402*598139dcSAndroid Build Coastguard Worker                 GTEST_LOG_(INFO)
403*598139dcSAndroid Build Coastguard Worker                     << "input = first(" << first_timestamp << ")\n";
404*598139dcSAndroid Build Coastguard Worker             }
405*598139dcSAndroid Build Coastguard Worker             free(first_timestamp);
406*598139dcSAndroid Build Coastguard Worker             first_timestamp = NULL;
407*598139dcSAndroid Build Coastguard Worker         }
408*598139dcSAndroid Build Coastguard Worker         if (second_timestamp) {
409*598139dcSAndroid Build Coastguard Worker             found = found || !strcmp(input, second_timestamp);
410*598139dcSAndroid Build Coastguard Worker             if (!found) {
411*598139dcSAndroid Build Coastguard Worker                 GTEST_LOG_(INFO) << "input(" << input << ") != second("
412*598139dcSAndroid Build Coastguard Worker                                  << second_timestamp << ")\n";
413*598139dcSAndroid Build Coastguard Worker             }
414*598139dcSAndroid Build Coastguard Worker             free(second_timestamp);
415*598139dcSAndroid Build Coastguard Worker             second_timestamp = NULL;
416*598139dcSAndroid Build Coastguard Worker         }
417*598139dcSAndroid Build Coastguard Worker         if (!strcmp(input, last_timestamp)) {
418*598139dcSAndroid Build Coastguard Worker             last_timestamp_count = second_count;
419*598139dcSAndroid Build Coastguard Worker         }
420*598139dcSAndroid Build Coastguard Worker     }
421*598139dcSAndroid Build Coastguard Worker     pclose(fp);
422*598139dcSAndroid Build Coastguard Worker 
423*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(found);
424*598139dcSAndroid Build Coastguard Worker     if (!found) {
425*598139dcSAndroid Build Coastguard Worker         if (first_timestamp) {
426*598139dcSAndroid Build Coastguard Worker             GTEST_LOG_(INFO) << "first = " << first_timestamp << "\n";
427*598139dcSAndroid Build Coastguard Worker         }
428*598139dcSAndroid Build Coastguard Worker         if (second_timestamp) {
429*598139dcSAndroid Build Coastguard Worker             GTEST_LOG_(INFO) << "second = " << second_timestamp << "\n";
430*598139dcSAndroid Build Coastguard Worker         }
431*598139dcSAndroid Build Coastguard Worker         if (last_timestamp) {
432*598139dcSAndroid Build Coastguard Worker             GTEST_LOG_(INFO) << "last = " << last_timestamp << "\n";
433*598139dcSAndroid Build Coastguard Worker         }
434*598139dcSAndroid Build Coastguard Worker     }
435*598139dcSAndroid Build Coastguard Worker     free(last_timestamp);
436*598139dcSAndroid Build Coastguard Worker     last_timestamp = NULL;
437*598139dcSAndroid Build Coastguard Worker     free(first_timestamp);
438*598139dcSAndroid Build Coastguard Worker     free(second_timestamp);
439*598139dcSAndroid Build Coastguard Worker 
440*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(first_timestamp == NULL);
441*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(second_timestamp == NULL);
442*598139dcSAndroid Build Coastguard Worker     EXPECT_LE(count, second_count);
443*598139dcSAndroid Build Coastguard Worker     EXPECT_LE(count, last_timestamp_count);
444*598139dcSAndroid Build Coastguard Worker }
445*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_time)446*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_time) {
447*598139dcSAndroid Build Coastguard Worker     do_tail_time(logcat_executable " -v long -v nsec -b all");
448*598139dcSAndroid Build Coastguard Worker }
449*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,tail_time_epoch)450*598139dcSAndroid Build Coastguard Worker TEST(logcat, tail_time_epoch) {
451*598139dcSAndroid Build Coastguard Worker     do_tail_time(logcat_executable " -v long -v nsec -v epoch -b all");
452*598139dcSAndroid Build Coastguard Worker }
453*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,End_to_End)454*598139dcSAndroid Build Coastguard Worker TEST(logcat, End_to_End) {
455*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
456*598139dcSAndroid Build Coastguard Worker 
457*598139dcSAndroid Build Coastguard Worker     log_time ts(CLOCK_MONOTONIC);
458*598139dcSAndroid Build Coastguard Worker 
459*598139dcSAndroid Build Coastguard Worker     ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
460*598139dcSAndroid Build Coastguard Worker 
461*598139dcSAndroid Build Coastguard Worker     FILE* fp;
462*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL !=
463*598139dcSAndroid Build Coastguard Worker                 (fp = popen(logcat_executable " -v brief -b events -t 100 2>/dev/null", "r")));
464*598139dcSAndroid Build Coastguard Worker 
465*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
466*598139dcSAndroid Build Coastguard Worker 
467*598139dcSAndroid Build Coastguard Worker     int count = 0;
468*598139dcSAndroid Build Coastguard Worker 
469*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
470*598139dcSAndroid Build Coastguard Worker         int p;
471*598139dcSAndroid Build Coastguard Worker         unsigned long long t;
472*598139dcSAndroid Build Coastguard Worker 
473*598139dcSAndroid Build Coastguard Worker         if ((2 != sscanf(buffer, "I/[0]     ( %d): %llu", &p, &t)) ||
474*598139dcSAndroid Build Coastguard Worker             (p != pid)) {
475*598139dcSAndroid Build Coastguard Worker             continue;
476*598139dcSAndroid Build Coastguard Worker         }
477*598139dcSAndroid Build Coastguard Worker 
478*598139dcSAndroid Build Coastguard Worker         log_time* tx = reinterpret_cast<log_time*>(&t);
479*598139dcSAndroid Build Coastguard Worker         if (ts == *tx) {
480*598139dcSAndroid Build Coastguard Worker             ++count;
481*598139dcSAndroid Build Coastguard Worker         }
482*598139dcSAndroid Build Coastguard Worker     }
483*598139dcSAndroid Build Coastguard Worker 
484*598139dcSAndroid Build Coastguard Worker     pclose(fp);
485*598139dcSAndroid Build Coastguard Worker 
486*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(1, count);
487*598139dcSAndroid Build Coastguard Worker }
488*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,End_to_End_multitude)489*598139dcSAndroid Build Coastguard Worker TEST(logcat, End_to_End_multitude) {
490*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
491*598139dcSAndroid Build Coastguard Worker 
492*598139dcSAndroid Build Coastguard Worker     log_time ts(CLOCK_MONOTONIC);
493*598139dcSAndroid Build Coastguard Worker 
494*598139dcSAndroid Build Coastguard Worker     ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
495*598139dcSAndroid Build Coastguard Worker 
496*598139dcSAndroid Build Coastguard Worker     FILE* fp[256] = {};  // does this count as a multitude!
497*598139dcSAndroid Build Coastguard Worker     size_t num = 0;
498*598139dcSAndroid Build Coastguard Worker     do {
499*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(NULL != (fp[num] = popen(logcat_executable " -v brief -b events -t 100", "r")));
500*598139dcSAndroid Build Coastguard Worker         if (!fp[num]) {
501*598139dcSAndroid Build Coastguard Worker             fprintf(stderr,
502*598139dcSAndroid Build Coastguard Worker                     "WARNING: limiting to %zu simultaneous logcat operations\n",
503*598139dcSAndroid Build Coastguard Worker                     num);
504*598139dcSAndroid Build Coastguard Worker             break;
505*598139dcSAndroid Build Coastguard Worker         }
506*598139dcSAndroid Build Coastguard Worker     } while (++num < sizeof(fp) / sizeof(fp[0]));
507*598139dcSAndroid Build Coastguard Worker 
508*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
509*598139dcSAndroid Build Coastguard Worker 
510*598139dcSAndroid Build Coastguard Worker     size_t count = 0;
511*598139dcSAndroid Build Coastguard Worker 
512*598139dcSAndroid Build Coastguard Worker     for (size_t idx = 0; idx < sizeof(fp) / sizeof(fp[0]); ++idx) {
513*598139dcSAndroid Build Coastguard Worker         if (!fp[idx]) break;
514*598139dcSAndroid Build Coastguard Worker         while (fgets(buffer, sizeof(buffer), fp[idx])) {
515*598139dcSAndroid Build Coastguard Worker             int p;
516*598139dcSAndroid Build Coastguard Worker             unsigned long long t;
517*598139dcSAndroid Build Coastguard Worker 
518*598139dcSAndroid Build Coastguard Worker             if ((2 != sscanf(buffer, "I/[0]     ( %d): %llu", &p, &t)) ||
519*598139dcSAndroid Build Coastguard Worker                 (p != pid)) {
520*598139dcSAndroid Build Coastguard Worker                 continue;
521*598139dcSAndroid Build Coastguard Worker             }
522*598139dcSAndroid Build Coastguard Worker 
523*598139dcSAndroid Build Coastguard Worker             log_time* tx = reinterpret_cast<log_time*>(&t);
524*598139dcSAndroid Build Coastguard Worker             if (ts == *tx) {
525*598139dcSAndroid Build Coastguard Worker                 ++count;
526*598139dcSAndroid Build Coastguard Worker             }
527*598139dcSAndroid Build Coastguard Worker         }
528*598139dcSAndroid Build Coastguard Worker 
529*598139dcSAndroid Build Coastguard Worker         pclose(fp[idx]);
530*598139dcSAndroid Build Coastguard Worker     }
531*598139dcSAndroid Build Coastguard Worker 
532*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(num, count);
533*598139dcSAndroid Build Coastguard Worker }
534*598139dcSAndroid Build Coastguard Worker 
get_groups(const char * cmd)535*598139dcSAndroid Build Coastguard Worker static int get_groups(const char* cmd) {
536*598139dcSAndroid Build Coastguard Worker     FILE* fp;
537*598139dcSAndroid Build Coastguard Worker 
538*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(NULL != (fp = popen(cmd, "r")));
539*598139dcSAndroid Build Coastguard Worker 
540*598139dcSAndroid Build Coastguard Worker     if (fp == NULL) {
541*598139dcSAndroid Build Coastguard Worker         return 0;
542*598139dcSAndroid Build Coastguard Worker     }
543*598139dcSAndroid Build Coastguard Worker 
544*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
545*598139dcSAndroid Build Coastguard Worker 
546*598139dcSAndroid Build Coastguard Worker     int count = 0;
547*598139dcSAndroid Build Coastguard Worker 
548*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
549*598139dcSAndroid Build Coastguard Worker         int size, consumed, readable, max, payload;
550*598139dcSAndroid Build Coastguard Worker         char size_mult[4], consumed_mult[4], readable_mult[4];
551*598139dcSAndroid Build Coastguard Worker         long full_size, full_consumed;
552*598139dcSAndroid Build Coastguard Worker 
553*598139dcSAndroid Build Coastguard Worker         size = consumed = max = payload = 0;
554*598139dcSAndroid Build Coastguard Worker         // NB: crash log can be very small, not hit a Kb of consumed space
555*598139dcSAndroid Build Coastguard Worker         //     doubly lucky we are not including it.
556*598139dcSAndroid Build Coastguard Worker         EXPECT_EQ(8, sscanf(buffer,
557*598139dcSAndroid Build Coastguard Worker                             "%*s ring buffer is %d %3s (%d %3s consumed, %d %3s readable),"
558*598139dcSAndroid Build Coastguard Worker                             " max entry is %d B, max payload is %d B",
559*598139dcSAndroid Build Coastguard Worker                             &size, size_mult, &consumed, consumed_mult, &readable, readable_mult,
560*598139dcSAndroid Build Coastguard Worker                             &max, &payload))
561*598139dcSAndroid Build Coastguard Worker                 << "Parse error on: " << buffer;
562*598139dcSAndroid Build Coastguard Worker         full_size = size;
563*598139dcSAndroid Build Coastguard Worker         switch (size_mult[0]) {
564*598139dcSAndroid Build Coastguard Worker             case 'G':
565*598139dcSAndroid Build Coastguard Worker                 full_size *= 1024;
566*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
567*598139dcSAndroid Build Coastguard Worker             case 'M':
568*598139dcSAndroid Build Coastguard Worker                 full_size *= 1024;
569*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
570*598139dcSAndroid Build Coastguard Worker             case 'K':
571*598139dcSAndroid Build Coastguard Worker                 full_size *= 1024;
572*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
573*598139dcSAndroid Build Coastguard Worker             case 'B':
574*598139dcSAndroid Build Coastguard Worker                 break;
575*598139dcSAndroid Build Coastguard Worker             default:
576*598139dcSAndroid Build Coastguard Worker                 ADD_FAILURE() << "Parse error on multiplier: " << size_mult;
577*598139dcSAndroid Build Coastguard Worker         }
578*598139dcSAndroid Build Coastguard Worker         full_consumed = consumed;
579*598139dcSAndroid Build Coastguard Worker         switch (consumed_mult[0]) {
580*598139dcSAndroid Build Coastguard Worker             case 'G':
581*598139dcSAndroid Build Coastguard Worker                 full_consumed *= 1024;
582*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
583*598139dcSAndroid Build Coastguard Worker             case 'M':
584*598139dcSAndroid Build Coastguard Worker                 full_consumed *= 1024;
585*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
586*598139dcSAndroid Build Coastguard Worker             case 'K':
587*598139dcSAndroid Build Coastguard Worker                 full_consumed *= 1024;
588*598139dcSAndroid Build Coastguard Worker                 FALLTHROUGH_INTENDED;
589*598139dcSAndroid Build Coastguard Worker             case 'B':
590*598139dcSAndroid Build Coastguard Worker                 break;
591*598139dcSAndroid Build Coastguard Worker             default:
592*598139dcSAndroid Build Coastguard Worker                 ADD_FAILURE() << "Parse error on multiplier: " << consumed_mult;
593*598139dcSAndroid Build Coastguard Worker         }
594*598139dcSAndroid Build Coastguard Worker         EXPECT_GT((full_size * 9) / 4, full_consumed);
595*598139dcSAndroid Build Coastguard Worker         EXPECT_GT(full_size, max);
596*598139dcSAndroid Build Coastguard Worker         EXPECT_GT(max, payload);
597*598139dcSAndroid Build Coastguard Worker 
598*598139dcSAndroid Build Coastguard Worker         if ((((full_size * 9) / 4) >= full_consumed) && (full_size > max) &&
599*598139dcSAndroid Build Coastguard Worker             (max > payload)) {
600*598139dcSAndroid Build Coastguard Worker             ++count;
601*598139dcSAndroid Build Coastguard Worker         }
602*598139dcSAndroid Build Coastguard Worker     }
603*598139dcSAndroid Build Coastguard Worker 
604*598139dcSAndroid Build Coastguard Worker     pclose(fp);
605*598139dcSAndroid Build Coastguard Worker 
606*598139dcSAndroid Build Coastguard Worker     return count;
607*598139dcSAndroid Build Coastguard Worker }
608*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,get_size)609*598139dcSAndroid Build Coastguard Worker TEST(logcat, get_size) {
610*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(4, get_groups(logcat_executable
611*598139dcSAndroid Build Coastguard Worker                             " -v brief -b radio -b events -b system -b "
612*598139dcSAndroid Build Coastguard Worker                             "main -g 2>/dev/null"));
613*598139dcSAndroid Build Coastguard Worker }
614*598139dcSAndroid Build Coastguard Worker 
615*598139dcSAndroid Build Coastguard Worker // duplicate test for get_size, but use comma-separated list of buffers
TEST(logcat,multiple_buffer)616*598139dcSAndroid Build Coastguard Worker TEST(logcat, multiple_buffer) {
617*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(
618*598139dcSAndroid Build Coastguard Worker         4, get_groups(logcat_executable
619*598139dcSAndroid Build Coastguard Worker                       " -v brief -b radio,events,system,main -g 2>/dev/null"));
620*598139dcSAndroid Build Coastguard Worker }
621*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,bad_buffer)622*598139dcSAndroid Build Coastguard Worker TEST(logcat, bad_buffer) {
623*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(0,
624*598139dcSAndroid Build Coastguard Worker               get_groups(
625*598139dcSAndroid Build Coastguard Worker                   logcat_executable
626*598139dcSAndroid Build Coastguard Worker                   " -v brief -b radio,events,bogo,system,main -g 2>/dev/null"));
627*598139dcSAndroid Build Coastguard Worker }
628*598139dcSAndroid Build Coastguard Worker 
629*598139dcSAndroid Build Coastguard Worker #ifndef logcat
caught_blocking(int signum)630*598139dcSAndroid Build Coastguard Worker static void caught_blocking(int signum) {
631*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xDEADBEEFA55A0000ULL;
632*598139dcSAndroid Build Coastguard Worker 
633*598139dcSAndroid Build Coastguard Worker     v += getpid() & 0xFFFF;
634*598139dcSAndroid Build Coastguard Worker     if (signum == 0) ++v;
635*598139dcSAndroid Build Coastguard Worker 
636*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
637*598139dcSAndroid Build Coastguard Worker }
638*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,blocking)639*598139dcSAndroid Build Coastguard Worker TEST(logcat, blocking) {
640*598139dcSAndroid Build Coastguard Worker     FILE* fp;
641*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xDEADBEEFA55F0000ULL;
642*598139dcSAndroid Build Coastguard Worker 
643*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
644*598139dcSAndroid Build Coastguard Worker 
645*598139dcSAndroid Build Coastguard Worker     v += pid & 0xFFFF;
646*598139dcSAndroid Build Coastguard Worker 
647*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
648*598139dcSAndroid Build Coastguard Worker 
649*598139dcSAndroid Build Coastguard Worker     v &= 0xFFFFFFFFFFFAFFFFULL;
650*598139dcSAndroid Build Coastguard Worker 
651*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(
652*598139dcSAndroid Build Coastguard Worker         NULL !=
653*598139dcSAndroid Build Coastguard Worker         (fp = popen("( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
654*598139dcSAndroid Build Coastguard Worker                     " logcat -v brief -b events 2>&1",
655*598139dcSAndroid Build Coastguard Worker                     "r")));
656*598139dcSAndroid Build Coastguard Worker 
657*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
658*598139dcSAndroid Build Coastguard Worker 
659*598139dcSAndroid Build Coastguard Worker     int count = 0;
660*598139dcSAndroid Build Coastguard Worker 
661*598139dcSAndroid Build Coastguard Worker     int signals = 0;
662*598139dcSAndroid Build Coastguard Worker 
663*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, caught_blocking);
664*598139dcSAndroid Build Coastguard Worker     alarm(2);
665*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
666*598139dcSAndroid Build Coastguard Worker         if (!strncmp(buffer, "DONE", 4)) {
667*598139dcSAndroid Build Coastguard Worker             break;
668*598139dcSAndroid Build Coastguard Worker         }
669*598139dcSAndroid Build Coastguard Worker 
670*598139dcSAndroid Build Coastguard Worker         ++count;
671*598139dcSAndroid Build Coastguard Worker 
672*598139dcSAndroid Build Coastguard Worker         int p;
673*598139dcSAndroid Build Coastguard Worker         unsigned long long l;
674*598139dcSAndroid Build Coastguard Worker 
675*598139dcSAndroid Build Coastguard Worker         if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l)) || (p != pid)) {
676*598139dcSAndroid Build Coastguard Worker             continue;
677*598139dcSAndroid Build Coastguard Worker         }
678*598139dcSAndroid Build Coastguard Worker 
679*598139dcSAndroid Build Coastguard Worker         if (l == v) {
680*598139dcSAndroid Build Coastguard Worker             ++signals;
681*598139dcSAndroid Build Coastguard Worker             break;
682*598139dcSAndroid Build Coastguard Worker         }
683*598139dcSAndroid Build Coastguard Worker     }
684*598139dcSAndroid Build Coastguard Worker     alarm(0);
685*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, SIG_DFL);
686*598139dcSAndroid Build Coastguard Worker 
687*598139dcSAndroid Build Coastguard Worker     // Generate SIGPIPE
688*598139dcSAndroid Build Coastguard Worker     fclose(fp);
689*598139dcSAndroid Build Coastguard Worker     caught_blocking(0);
690*598139dcSAndroid Build Coastguard Worker 
691*598139dcSAndroid Build Coastguard Worker     pclose(fp);
692*598139dcSAndroid Build Coastguard Worker 
693*598139dcSAndroid Build Coastguard Worker     EXPECT_GE(count, 2);
694*598139dcSAndroid Build Coastguard Worker 
695*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(signals, 1);
696*598139dcSAndroid Build Coastguard Worker }
697*598139dcSAndroid Build Coastguard Worker 
caught_blocking_tail(int signum)698*598139dcSAndroid Build Coastguard Worker static void caught_blocking_tail(int signum) {
699*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xA55ADEADBEEF0000ULL;
700*598139dcSAndroid Build Coastguard Worker 
701*598139dcSAndroid Build Coastguard Worker     v += getpid() & 0xFFFF;
702*598139dcSAndroid Build Coastguard Worker     if (signum == 0) ++v;
703*598139dcSAndroid Build Coastguard Worker 
704*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
705*598139dcSAndroid Build Coastguard Worker }
706*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,blocking_tail)707*598139dcSAndroid Build Coastguard Worker TEST(logcat, blocking_tail) {
708*598139dcSAndroid Build Coastguard Worker     FILE* fp;
709*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xA55FDEADBEEF0000ULL;
710*598139dcSAndroid Build Coastguard Worker 
711*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
712*598139dcSAndroid Build Coastguard Worker 
713*598139dcSAndroid Build Coastguard Worker     v += pid & 0xFFFF;
714*598139dcSAndroid Build Coastguard Worker 
715*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
716*598139dcSAndroid Build Coastguard Worker 
717*598139dcSAndroid Build Coastguard Worker     v &= 0xFFFAFFFFFFFFFFFFULL;
718*598139dcSAndroid Build Coastguard Worker 
719*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(
720*598139dcSAndroid Build Coastguard Worker         NULL !=
721*598139dcSAndroid Build Coastguard Worker         (fp = popen("( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
722*598139dcSAndroid Build Coastguard Worker                     " logcat -v brief -b events -T 5 2>&1",
723*598139dcSAndroid Build Coastguard Worker                     "r")));
724*598139dcSAndroid Build Coastguard Worker 
725*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
726*598139dcSAndroid Build Coastguard Worker 
727*598139dcSAndroid Build Coastguard Worker     int count = 0;
728*598139dcSAndroid Build Coastguard Worker 
729*598139dcSAndroid Build Coastguard Worker     int signals = 0;
730*598139dcSAndroid Build Coastguard Worker 
731*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, caught_blocking_tail);
732*598139dcSAndroid Build Coastguard Worker     alarm(2);
733*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
734*598139dcSAndroid Build Coastguard Worker         if (!strncmp(buffer, "DONE", 4)) {
735*598139dcSAndroid Build Coastguard Worker             break;
736*598139dcSAndroid Build Coastguard Worker         }
737*598139dcSAndroid Build Coastguard Worker 
738*598139dcSAndroid Build Coastguard Worker         ++count;
739*598139dcSAndroid Build Coastguard Worker 
740*598139dcSAndroid Build Coastguard Worker         int p;
741*598139dcSAndroid Build Coastguard Worker         unsigned long long l;
742*598139dcSAndroid Build Coastguard Worker 
743*598139dcSAndroid Build Coastguard Worker         if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l)) || (p != pid)) {
744*598139dcSAndroid Build Coastguard Worker             continue;
745*598139dcSAndroid Build Coastguard Worker         }
746*598139dcSAndroid Build Coastguard Worker 
747*598139dcSAndroid Build Coastguard Worker         if (l == v) {
748*598139dcSAndroid Build Coastguard Worker             if (count >= 5) {
749*598139dcSAndroid Build Coastguard Worker                 ++signals;
750*598139dcSAndroid Build Coastguard Worker             }
751*598139dcSAndroid Build Coastguard Worker             break;
752*598139dcSAndroid Build Coastguard Worker         }
753*598139dcSAndroid Build Coastguard Worker     }
754*598139dcSAndroid Build Coastguard Worker     alarm(0);
755*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, SIG_DFL);
756*598139dcSAndroid Build Coastguard Worker 
757*598139dcSAndroid Build Coastguard Worker     // Generate SIGPIPE
758*598139dcSAndroid Build Coastguard Worker     fclose(fp);
759*598139dcSAndroid Build Coastguard Worker     caught_blocking_tail(0);
760*598139dcSAndroid Build Coastguard Worker 
761*598139dcSAndroid Build Coastguard Worker     pclose(fp);
762*598139dcSAndroid Build Coastguard Worker 
763*598139dcSAndroid Build Coastguard Worker     EXPECT_GE(count, 2);
764*598139dcSAndroid Build Coastguard Worker 
765*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(signals, 1);
766*598139dcSAndroid Build Coastguard Worker }
767*598139dcSAndroid Build Coastguard Worker #endif
768*598139dcSAndroid Build Coastguard Worker 
769*598139dcSAndroid Build Coastguard Worker // meant to be handed to ASSERT_FALSE / EXPECT_FALSE to expand the message
IsFalse(int ret,const char * command)770*598139dcSAndroid Build Coastguard Worker static testing::AssertionResult IsFalse(int ret, const char* command) {
771*598139dcSAndroid Build Coastguard Worker     return ret ? (testing::AssertionSuccess()
772*598139dcSAndroid Build Coastguard Worker                   << "ret=" << ret << " command=\"" << command << "\"")
773*598139dcSAndroid Build Coastguard Worker                : testing::AssertionFailure();
774*598139dcSAndroid Build Coastguard Worker }
775*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate)776*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate) {
777*598139dcSAndroid Build Coastguard Worker     static const char form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
778*598139dcSAndroid Build Coastguard Worker     char buf[sizeof(form)];
779*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != mkdtemp(strcpy(buf, form)));
780*598139dcSAndroid Build Coastguard Worker 
781*598139dcSAndroid Build Coastguard Worker     static const char comm[] = logcat_executable
782*598139dcSAndroid Build Coastguard Worker         " -b radio -b events -b system -b main"
783*598139dcSAndroid Build Coastguard Worker         " -d -f %s/log.txt -n 7 -r 1";
784*598139dcSAndroid Build Coastguard Worker     char command[sizeof(buf) + sizeof(comm)];
785*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), comm, buf);
786*598139dcSAndroid Build Coastguard Worker 
787*598139dcSAndroid Build Coastguard Worker     int ret;
788*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(ret = system(command), command));
789*598139dcSAndroid Build Coastguard Worker     if (!ret) {
790*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), "ls -s %s 2>/dev/null", buf);
791*598139dcSAndroid Build Coastguard Worker 
792*598139dcSAndroid Build Coastguard Worker         FILE* fp;
793*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(NULL != (fp = popen(command, "r")));
794*598139dcSAndroid Build Coastguard Worker         if (fp) {
795*598139dcSAndroid Build Coastguard Worker             char buffer[BIG_BUFFER];
796*598139dcSAndroid Build Coastguard Worker             int count = 0;
797*598139dcSAndroid Build Coastguard Worker 
798*598139dcSAndroid Build Coastguard Worker             while (fgets(buffer, sizeof(buffer), fp)) {
799*598139dcSAndroid Build Coastguard Worker                 static const char total[] = "total ";
800*598139dcSAndroid Build Coastguard Worker                 int num;
801*598139dcSAndroid Build Coastguard Worker                 char c;
802*598139dcSAndroid Build Coastguard Worker 
803*598139dcSAndroid Build Coastguard Worker                 if ((2 == sscanf(buffer, "%d log.tx%c", &num, &c)) &&
804*598139dcSAndroid Build Coastguard Worker                     (num <= 40)) {
805*598139dcSAndroid Build Coastguard Worker                     ++count;
806*598139dcSAndroid Build Coastguard Worker                 } else if (strncmp(buffer, total, sizeof(total) - 1)) {
807*598139dcSAndroid Build Coastguard Worker                     fprintf(stderr, "WARNING: Parse error: %s", buffer);
808*598139dcSAndroid Build Coastguard Worker                 }
809*598139dcSAndroid Build Coastguard Worker             }
810*598139dcSAndroid Build Coastguard Worker             pclose(fp);
811*598139dcSAndroid Build Coastguard Worker             if ((count != 7) && (count != 8)) {
812*598139dcSAndroid Build Coastguard Worker                 fprintf(stderr, "count=%d\n", count);
813*598139dcSAndroid Build Coastguard Worker             }
814*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(count == 7 || count == 8);
815*598139dcSAndroid Build Coastguard Worker         }
816*598139dcSAndroid Build Coastguard Worker     }
817*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), "rm -rf %s", buf);
818*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(system(command), command));
819*598139dcSAndroid Build Coastguard Worker }
820*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate_suffix)821*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate_suffix) {
822*598139dcSAndroid Build Coastguard Worker     static const char tmp_out_dir_form[] =
823*598139dcSAndroid Build Coastguard Worker         "/data/local/tmp/logcat.logrotate.XXXXXX";
824*598139dcSAndroid Build Coastguard Worker     char tmp_out_dir[sizeof(tmp_out_dir_form)];
825*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
826*598139dcSAndroid Build Coastguard Worker 
827*598139dcSAndroid Build Coastguard Worker     static const char logcat_cmd[] = logcat_executable
828*598139dcSAndroid Build Coastguard Worker         " -b radio -b events -b system -b main"
829*598139dcSAndroid Build Coastguard Worker         " -d -f %s/log.txt -n 10 -r 1";
830*598139dcSAndroid Build Coastguard Worker     char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd)];
831*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir);
832*598139dcSAndroid Build Coastguard Worker 
833*598139dcSAndroid Build Coastguard Worker     int ret;
834*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(ret = system(command), command));
835*598139dcSAndroid Build Coastguard Worker     if (!ret) {
836*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), "ls %s 2>/dev/null", tmp_out_dir);
837*598139dcSAndroid Build Coastguard Worker 
838*598139dcSAndroid Build Coastguard Worker         FILE* fp;
839*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(NULL != (fp = popen(command, "r")));
840*598139dcSAndroid Build Coastguard Worker         char buffer[BIG_BUFFER];
841*598139dcSAndroid Build Coastguard Worker         int log_file_count = 0;
842*598139dcSAndroid Build Coastguard Worker 
843*598139dcSAndroid Build Coastguard Worker         while (fgets(buffer, sizeof(buffer), fp)) {
844*598139dcSAndroid Build Coastguard Worker             static const char rotated_log_filename_prefix[] = "log.txt.";
845*598139dcSAndroid Build Coastguard Worker             static const size_t rotated_log_filename_prefix_len =
846*598139dcSAndroid Build Coastguard Worker                 strlen(rotated_log_filename_prefix);
847*598139dcSAndroid Build Coastguard Worker             static const char log_filename[] = "log.txt";
848*598139dcSAndroid Build Coastguard Worker 
849*598139dcSAndroid Build Coastguard Worker             if (!strncmp(buffer, rotated_log_filename_prefix,
850*598139dcSAndroid Build Coastguard Worker                          rotated_log_filename_prefix_len)) {
851*598139dcSAndroid Build Coastguard Worker                 // Rotated file should have form log.txt.##
852*598139dcSAndroid Build Coastguard Worker                 char* rotated_log_filename_suffix =
853*598139dcSAndroid Build Coastguard Worker                     buffer + rotated_log_filename_prefix_len;
854*598139dcSAndroid Build Coastguard Worker                 char* endptr;
855*598139dcSAndroid Build Coastguard Worker                 const long int suffix_value =
856*598139dcSAndroid Build Coastguard Worker                     strtol(rotated_log_filename_suffix, &endptr, 10);
857*598139dcSAndroid Build Coastguard Worker                 EXPECT_EQ(rotated_log_filename_suffix + 2, endptr);
858*598139dcSAndroid Build Coastguard Worker                 EXPECT_LE(suffix_value, 10);
859*598139dcSAndroid Build Coastguard Worker                 EXPECT_GT(suffix_value, 0);
860*598139dcSAndroid Build Coastguard Worker                 ++log_file_count;
861*598139dcSAndroid Build Coastguard Worker                 continue;
862*598139dcSAndroid Build Coastguard Worker             }
863*598139dcSAndroid Build Coastguard Worker 
864*598139dcSAndroid Build Coastguard Worker             if (!strncmp(buffer, log_filename, strlen(log_filename))) {
865*598139dcSAndroid Build Coastguard Worker                 ++log_file_count;
866*598139dcSAndroid Build Coastguard Worker                 continue;
867*598139dcSAndroid Build Coastguard Worker             }
868*598139dcSAndroid Build Coastguard Worker 
869*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "ERROR: Unexpected file: %s", buffer);
870*598139dcSAndroid Build Coastguard Worker             ADD_FAILURE();
871*598139dcSAndroid Build Coastguard Worker         }
872*598139dcSAndroid Build Coastguard Worker         pclose(fp);
873*598139dcSAndroid Build Coastguard Worker         EXPECT_EQ(log_file_count, 11);
874*598139dcSAndroid Build Coastguard Worker     }
875*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), "rm -rf %s", tmp_out_dir);
876*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(system(command), command));
877*598139dcSAndroid Build Coastguard Worker }
878*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate_continue)879*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate_continue) {
880*598139dcSAndroid Build Coastguard Worker     static const char tmp_out_dir_form[] =
881*598139dcSAndroid Build Coastguard Worker         "/data/local/tmp/logcat.logrotate.XXXXXX";
882*598139dcSAndroid Build Coastguard Worker     char tmp_out_dir[sizeof(tmp_out_dir_form)];
883*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
884*598139dcSAndroid Build Coastguard Worker 
885*598139dcSAndroid Build Coastguard Worker     static const char log_filename[] = "log.txt";
886*598139dcSAndroid Build Coastguard Worker     static const char logcat_cmd[] =
887*598139dcSAndroid Build Coastguard Worker         logcat_executable " -b all -v nsec -d -f %s/%s -n 256 -r 1024";
888*598139dcSAndroid Build Coastguard Worker     static const char cleanup_cmd[] = "rm -rf %s";
889*598139dcSAndroid Build Coastguard Worker     char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd) + sizeof(log_filename)];
890*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
891*598139dcSAndroid Build Coastguard Worker 
892*598139dcSAndroid Build Coastguard Worker     int ret;
893*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(ret = system(command), command));
894*598139dcSAndroid Build Coastguard Worker     if (ret) {
895*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
896*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(system(command), command));
897*598139dcSAndroid Build Coastguard Worker         return;
898*598139dcSAndroid Build Coastguard Worker     }
899*598139dcSAndroid Build Coastguard Worker     FILE* fp;
900*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), "%s/%s", tmp_out_dir, log_filename);
901*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(NULL != ((fp = fopen(command, "r"))));
902*598139dcSAndroid Build Coastguard Worker     if (!fp) {
903*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
904*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(system(command), command));
905*598139dcSAndroid Build Coastguard Worker         return;
906*598139dcSAndroid Build Coastguard Worker     }
907*598139dcSAndroid Build Coastguard Worker     char* line = NULL;
908*598139dcSAndroid Build Coastguard Worker     char* last_line =
909*598139dcSAndroid Build Coastguard Worker         NULL;  // this line is allowed to stutter, one-line overlap
910*598139dcSAndroid Build Coastguard Worker     char* second_last_line = NULL;  // should never stutter
911*598139dcSAndroid Build Coastguard Worker     char* first_line = NULL;        // help diagnose failure?
912*598139dcSAndroid Build Coastguard Worker     size_t len = 0;
913*598139dcSAndroid Build Coastguard Worker     while (getline(&line, &len, fp) != -1) {
914*598139dcSAndroid Build Coastguard Worker         if (!first_line) {
915*598139dcSAndroid Build Coastguard Worker             first_line = line;
916*598139dcSAndroid Build Coastguard Worker             line = NULL;
917*598139dcSAndroid Build Coastguard Worker             continue;
918*598139dcSAndroid Build Coastguard Worker         }
919*598139dcSAndroid Build Coastguard Worker         free(second_last_line);
920*598139dcSAndroid Build Coastguard Worker         second_last_line = last_line;
921*598139dcSAndroid Build Coastguard Worker         last_line = line;
922*598139dcSAndroid Build Coastguard Worker         line = NULL;
923*598139dcSAndroid Build Coastguard Worker     }
924*598139dcSAndroid Build Coastguard Worker     fclose(fp);
925*598139dcSAndroid Build Coastguard Worker     free(line);
926*598139dcSAndroid Build Coastguard Worker     if (second_last_line == NULL) {
927*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "No second to last line, using last, test may fail\n");
928*598139dcSAndroid Build Coastguard Worker         second_last_line = last_line;
929*598139dcSAndroid Build Coastguard Worker         last_line = NULL;
930*598139dcSAndroid Build Coastguard Worker     }
931*598139dcSAndroid Build Coastguard Worker     free(last_line);
932*598139dcSAndroid Build Coastguard Worker     EXPECT_TRUE(NULL != second_last_line);
933*598139dcSAndroid Build Coastguard Worker     if (!second_last_line) {
934*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
935*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(system(command), command));
936*598139dcSAndroid Build Coastguard Worker         free(first_line);
937*598139dcSAndroid Build Coastguard Worker         return;
938*598139dcSAndroid Build Coastguard Worker     }
939*598139dcSAndroid Build Coastguard Worker     // re-run the command, it should only add a few lines more content if it
940*598139dcSAndroid Build Coastguard Worker     // continues where it left off.
941*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
942*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(ret = system(command), command));
943*598139dcSAndroid Build Coastguard Worker     if (ret) {
944*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
945*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(system(command), command));
946*598139dcSAndroid Build Coastguard Worker         free(second_last_line);
947*598139dcSAndroid Build Coastguard Worker         free(first_line);
948*598139dcSAndroid Build Coastguard Worker         return;
949*598139dcSAndroid Build Coastguard Worker     }
950*598139dcSAndroid Build Coastguard Worker     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir),
951*598139dcSAndroid Build Coastguard Worker                                                   closedir);
952*598139dcSAndroid Build Coastguard Worker     EXPECT_NE(nullptr, dir);
953*598139dcSAndroid Build Coastguard Worker     if (!dir) {
954*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
955*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(system(command), command));
956*598139dcSAndroid Build Coastguard Worker         free(second_last_line);
957*598139dcSAndroid Build Coastguard Worker         free(first_line);
958*598139dcSAndroid Build Coastguard Worker         return;
959*598139dcSAndroid Build Coastguard Worker     }
960*598139dcSAndroid Build Coastguard Worker     struct dirent* entry;
961*598139dcSAndroid Build Coastguard Worker     unsigned count = 0;
962*598139dcSAndroid Build Coastguard Worker     while ((entry = readdir(dir.get()))) {
963*598139dcSAndroid Build Coastguard Worker         if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
964*598139dcSAndroid Build Coastguard Worker             continue;
965*598139dcSAndroid Build Coastguard Worker         }
966*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command), "%s/%s", tmp_out_dir, entry->d_name);
967*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(NULL != ((fp = fopen(command, "r"))));
968*598139dcSAndroid Build Coastguard Worker         if (!fp) {
969*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "%s ?\n", command);
970*598139dcSAndroid Build Coastguard Worker             continue;
971*598139dcSAndroid Build Coastguard Worker         }
972*598139dcSAndroid Build Coastguard Worker         line = NULL;
973*598139dcSAndroid Build Coastguard Worker         size_t number = 0;
974*598139dcSAndroid Build Coastguard Worker         while (getline(&line, &len, fp) != -1) {
975*598139dcSAndroid Build Coastguard Worker             ++number;
976*598139dcSAndroid Build Coastguard Worker             if (!strcmp(line, second_last_line)) {
977*598139dcSAndroid Build Coastguard Worker                 EXPECT_TRUE(++count <= 1);
978*598139dcSAndroid Build Coastguard Worker                 fprintf(stderr, "%s(%zu):\n", entry->d_name, number);
979*598139dcSAndroid Build Coastguard Worker             }
980*598139dcSAndroid Build Coastguard Worker         }
981*598139dcSAndroid Build Coastguard Worker         fclose(fp);
982*598139dcSAndroid Build Coastguard Worker         free(line);
983*598139dcSAndroid Build Coastguard Worker         unlink(command);
984*598139dcSAndroid Build Coastguard Worker     }
985*598139dcSAndroid Build Coastguard Worker     if (count > 1) {
986*598139dcSAndroid Build Coastguard Worker         char* brk = strpbrk(second_last_line, "\r\n");
987*598139dcSAndroid Build Coastguard Worker         if (!brk) brk = second_last_line + strlen(second_last_line);
988*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "\"%.*s\" occurred %u times\n",
989*598139dcSAndroid Build Coastguard Worker                 (int)(brk - second_last_line), second_last_line, count);
990*598139dcSAndroid Build Coastguard Worker         if (first_line) {
991*598139dcSAndroid Build Coastguard Worker             brk = strpbrk(first_line, "\r\n");
992*598139dcSAndroid Build Coastguard Worker             if (!brk) brk = first_line + strlen(first_line);
993*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "\"%.*s\" was first line, fault?\n",
994*598139dcSAndroid Build Coastguard Worker                     (int)(brk - first_line), first_line);
995*598139dcSAndroid Build Coastguard Worker         }
996*598139dcSAndroid Build Coastguard Worker     }
997*598139dcSAndroid Build Coastguard Worker     free(second_last_line);
998*598139dcSAndroid Build Coastguard Worker     free(first_line);
999*598139dcSAndroid Build Coastguard Worker 
1000*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1001*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(system(command), command));
1002*598139dcSAndroid Build Coastguard Worker }
1003*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate_clear)1004*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate_clear) {
1005*598139dcSAndroid Build Coastguard Worker     static const char tmp_out_dir_form[] =
1006*598139dcSAndroid Build Coastguard Worker         "/data/local/tmp/logcat.logrotate.XXXXXX";
1007*598139dcSAndroid Build Coastguard Worker     char tmp_out_dir[sizeof(tmp_out_dir_form)];
1008*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
1009*598139dcSAndroid Build Coastguard Worker 
1010*598139dcSAndroid Build Coastguard Worker     static const char log_filename[] = "log.txt";
1011*598139dcSAndroid Build Coastguard Worker     static const unsigned num_val = 32;
1012*598139dcSAndroid Build Coastguard Worker     static const char logcat_cmd[] =
1013*598139dcSAndroid Build Coastguard Worker         logcat_executable " -b all -d -f %s/%s -n %d -r 1";
1014*598139dcSAndroid Build Coastguard Worker     static const char clear_cmd[] = " -c";
1015*598139dcSAndroid Build Coastguard Worker     static const char cleanup_cmd[] = "rm -rf %s";
1016*598139dcSAndroid Build Coastguard Worker     char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd) +
1017*598139dcSAndroid Build Coastguard Worker                  sizeof(log_filename) + sizeof(clear_cmd) + 32];
1018*598139dcSAndroid Build Coastguard Worker 
1019*598139dcSAndroid Build Coastguard Worker     // Run command with all data
1020*598139dcSAndroid Build Coastguard Worker     {
1021*598139dcSAndroid Build Coastguard Worker         snprintf(command, sizeof(command) - sizeof(clear_cmd), logcat_cmd,
1022*598139dcSAndroid Build Coastguard Worker                  tmp_out_dir, log_filename, num_val);
1023*598139dcSAndroid Build Coastguard Worker 
1024*598139dcSAndroid Build Coastguard Worker         int ret;
1025*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(ret = system(command), command));
1026*598139dcSAndroid Build Coastguard Worker         if (ret) {
1027*598139dcSAndroid Build Coastguard Worker             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1028*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(IsFalse(system(command), command));
1029*598139dcSAndroid Build Coastguard Worker             return;
1030*598139dcSAndroid Build Coastguard Worker         }
1031*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir),
1032*598139dcSAndroid Build Coastguard Worker                                                       closedir);
1033*598139dcSAndroid Build Coastguard Worker         EXPECT_NE(nullptr, dir);
1034*598139dcSAndroid Build Coastguard Worker         if (!dir) {
1035*598139dcSAndroid Build Coastguard Worker             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1036*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(IsFalse(system(command), command));
1037*598139dcSAndroid Build Coastguard Worker             return;
1038*598139dcSAndroid Build Coastguard Worker         }
1039*598139dcSAndroid Build Coastguard Worker         struct dirent* entry;
1040*598139dcSAndroid Build Coastguard Worker         unsigned count = 0;
1041*598139dcSAndroid Build Coastguard Worker         while ((entry = readdir(dir.get()))) {
1042*598139dcSAndroid Build Coastguard Worker             if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
1043*598139dcSAndroid Build Coastguard Worker                 continue;
1044*598139dcSAndroid Build Coastguard Worker             }
1045*598139dcSAndroid Build Coastguard Worker             ++count;
1046*598139dcSAndroid Build Coastguard Worker         }
1047*598139dcSAndroid Build Coastguard Worker         EXPECT_EQ(count, num_val + 1);
1048*598139dcSAndroid Build Coastguard Worker     }
1049*598139dcSAndroid Build Coastguard Worker 
1050*598139dcSAndroid Build Coastguard Worker     {
1051*598139dcSAndroid Build Coastguard Worker         // Now with -c option tacked onto the end
1052*598139dcSAndroid Build Coastguard Worker         strcat(command, clear_cmd);
1053*598139dcSAndroid Build Coastguard Worker 
1054*598139dcSAndroid Build Coastguard Worker         int ret;
1055*598139dcSAndroid Build Coastguard Worker         EXPECT_FALSE(IsFalse(ret = system(command), command));
1056*598139dcSAndroid Build Coastguard Worker         if (ret) {
1057*598139dcSAndroid Build Coastguard Worker             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1058*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(system(command));
1059*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(IsFalse(system(command), command));
1060*598139dcSAndroid Build Coastguard Worker             return;
1061*598139dcSAndroid Build Coastguard Worker         }
1062*598139dcSAndroid Build Coastguard Worker         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir),
1063*598139dcSAndroid Build Coastguard Worker                                                       closedir);
1064*598139dcSAndroid Build Coastguard Worker         EXPECT_NE(nullptr, dir);
1065*598139dcSAndroid Build Coastguard Worker         if (!dir) {
1066*598139dcSAndroid Build Coastguard Worker             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1067*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(IsFalse(system(command), command));
1068*598139dcSAndroid Build Coastguard Worker             return;
1069*598139dcSAndroid Build Coastguard Worker         }
1070*598139dcSAndroid Build Coastguard Worker         struct dirent* entry;
1071*598139dcSAndroid Build Coastguard Worker         unsigned count = 0;
1072*598139dcSAndroid Build Coastguard Worker         while ((entry = readdir(dir.get()))) {
1073*598139dcSAndroid Build Coastguard Worker             if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
1074*598139dcSAndroid Build Coastguard Worker                 continue;
1075*598139dcSAndroid Build Coastguard Worker             }
1076*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "Found %s/%s!!!\n", tmp_out_dir, entry->d_name);
1077*598139dcSAndroid Build Coastguard Worker             ++count;
1078*598139dcSAndroid Build Coastguard Worker         }
1079*598139dcSAndroid Build Coastguard Worker         EXPECT_EQ(count, 0U);
1080*598139dcSAndroid Build Coastguard Worker     }
1081*598139dcSAndroid Build Coastguard Worker 
1082*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1083*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(system(command), command));
1084*598139dcSAndroid Build Coastguard Worker }
1085*598139dcSAndroid Build Coastguard Worker 
logrotate_count_id(const char * logcat_cmd,const char * tmp_out_dir)1086*598139dcSAndroid Build Coastguard Worker static int logrotate_count_id(const char* logcat_cmd, const char* tmp_out_dir) {
1087*598139dcSAndroid Build Coastguard Worker     static const char log_filename[] = "log.txt";
1088*598139dcSAndroid Build Coastguard Worker     char command[strlen(tmp_out_dir) + strlen(logcat_cmd) +
1089*598139dcSAndroid Build Coastguard Worker                  strlen(log_filename) + 32];
1090*598139dcSAndroid Build Coastguard Worker 
1091*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
1092*598139dcSAndroid Build Coastguard Worker 
1093*598139dcSAndroid Build Coastguard Worker     int ret = system(command);
1094*598139dcSAndroid Build Coastguard Worker     if (ret) {
1095*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "system(\"%s\")=%d", command, ret);
1096*598139dcSAndroid Build Coastguard Worker         return -1;
1097*598139dcSAndroid Build Coastguard Worker     }
1098*598139dcSAndroid Build Coastguard Worker     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir),
1099*598139dcSAndroid Build Coastguard Worker                                                   closedir);
1100*598139dcSAndroid Build Coastguard Worker     if (!dir) {
1101*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "opendir(\"%s\") failed", tmp_out_dir);
1102*598139dcSAndroid Build Coastguard Worker         return -1;
1103*598139dcSAndroid Build Coastguard Worker     }
1104*598139dcSAndroid Build Coastguard Worker     struct dirent* entry;
1105*598139dcSAndroid Build Coastguard Worker     int count = 0;
1106*598139dcSAndroid Build Coastguard Worker     while ((entry = readdir(dir.get()))) {
1107*598139dcSAndroid Build Coastguard Worker         if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
1108*598139dcSAndroid Build Coastguard Worker             continue;
1109*598139dcSAndroid Build Coastguard Worker         }
1110*598139dcSAndroid Build Coastguard Worker         ++count;
1111*598139dcSAndroid Build Coastguard Worker     }
1112*598139dcSAndroid Build Coastguard Worker     return count;
1113*598139dcSAndroid Build Coastguard Worker }
1114*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate_id)1115*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate_id) {
1116*598139dcSAndroid Build Coastguard Worker     static const char logcat_cmd[] =
1117*598139dcSAndroid Build Coastguard Worker         logcat_executable " -b all -d -f %s/%s -n 32 -r 1 --id=test";
1118*598139dcSAndroid Build Coastguard Worker     static const char logcat_short_cmd[] =
1119*598139dcSAndroid Build Coastguard Worker         logcat_executable " -b all -t 10 -f %s/%s -n 32 -r 1 --id=test";
1120*598139dcSAndroid Build Coastguard Worker     static const char tmp_out_dir_form[] =
1121*598139dcSAndroid Build Coastguard Worker         "/data/local/tmp/logcat.logrotate.XXXXXX";
1122*598139dcSAndroid Build Coastguard Worker     static const char log_filename[] = "log.txt";
1123*598139dcSAndroid Build Coastguard Worker     char tmp_out_dir[strlen(tmp_out_dir_form) + 1];
1124*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
1125*598139dcSAndroid Build Coastguard Worker 
1126*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(logrotate_count_id(logcat_cmd, tmp_out_dir), 34);
1127*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
1128*598139dcSAndroid Build Coastguard Worker 
1129*598139dcSAndroid Build Coastguard Worker     char id_file[strlen(tmp_out_dir_form) + strlen(log_filename) + 5];
1130*598139dcSAndroid Build Coastguard Worker     snprintf(id_file, sizeof(id_file), "%s/%s.id", tmp_out_dir, log_filename);
1131*598139dcSAndroid Build Coastguard Worker     if (getuid() != 0) {
1132*598139dcSAndroid Build Coastguard Worker         chmod(id_file, 0);
1133*598139dcSAndroid Build Coastguard Worker         EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
1134*598139dcSAndroid Build Coastguard Worker     }
1135*598139dcSAndroid Build Coastguard Worker     unlink(id_file);
1136*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
1137*598139dcSAndroid Build Coastguard Worker 
1138*598139dcSAndroid Build Coastguard Worker     FILE* fp = fopen(id_file, "w");
1139*598139dcSAndroid Build Coastguard Worker     if (fp) {
1140*598139dcSAndroid Build Coastguard Worker         fprintf(fp, "not_a_test");
1141*598139dcSAndroid Build Coastguard Worker         fclose(fp);
1142*598139dcSAndroid Build Coastguard Worker     }
1143*598139dcSAndroid Build Coastguard Worker     if (getuid() != 0) {
1144*598139dcSAndroid Build Coastguard Worker         chmod(id_file,
1145*598139dcSAndroid Build Coastguard Worker               0);  // API to preserve content even with signature change
1146*598139dcSAndroid Build Coastguard Worker         ASSERT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
1147*598139dcSAndroid Build Coastguard Worker         chmod(id_file, 0600);
1148*598139dcSAndroid Build Coastguard Worker     }
1149*598139dcSAndroid Build Coastguard Worker 
1150*598139dcSAndroid Build Coastguard Worker     int new_signature;
1151*598139dcSAndroid Build Coastguard Worker     EXPECT_GE(
1152*598139dcSAndroid Build Coastguard Worker         (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)), 2);
1153*598139dcSAndroid Build Coastguard Worker     EXPECT_LT(new_signature, 34);
1154*598139dcSAndroid Build Coastguard Worker 
1155*598139dcSAndroid Build Coastguard Worker     static const char cleanup_cmd[] = "rm -rf %s";
1156*598139dcSAndroid Build Coastguard Worker     char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
1157*598139dcSAndroid Build Coastguard Worker     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
1158*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(system(command), command));
1159*598139dcSAndroid Build Coastguard Worker }
1160*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,logrotate_nodir)1161*598139dcSAndroid Build Coastguard Worker TEST(logcat, logrotate_nodir) {
1162*598139dcSAndroid Build Coastguard Worker     // expect logcat to error out on writing content and not exit(0) for nodir
1163*598139dcSAndroid Build Coastguard Worker     static const char command[] = logcat_executable
1164*598139dcSAndroid Build Coastguard Worker         " -b all -d"
1165*598139dcSAndroid Build Coastguard Worker         " -f /das/nein/gerfingerpoken/logcat/log.txt"
1166*598139dcSAndroid Build Coastguard Worker         " -n 256 -r 1024";
1167*598139dcSAndroid Build Coastguard Worker     EXPECT_FALSE(IsFalse(0 == system(command), command));
1168*598139dcSAndroid Build Coastguard Worker }
1169*598139dcSAndroid Build Coastguard Worker 
1170*598139dcSAndroid Build Coastguard Worker #ifndef logcat
caught_blocking_clear(int signum)1171*598139dcSAndroid Build Coastguard Worker static void caught_blocking_clear(int signum) {
1172*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xDEADBEEFA55C0000ULL;
1173*598139dcSAndroid Build Coastguard Worker 
1174*598139dcSAndroid Build Coastguard Worker     v += getpid() & 0xFFFF;
1175*598139dcSAndroid Build Coastguard Worker     if (signum == 0) ++v;
1176*598139dcSAndroid Build Coastguard Worker 
1177*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
1178*598139dcSAndroid Build Coastguard Worker }
1179*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,blocking_clear)1180*598139dcSAndroid Build Coastguard Worker TEST(logcat, blocking_clear) {
1181*598139dcSAndroid Build Coastguard Worker     FILE* fp;
1182*598139dcSAndroid Build Coastguard Worker     unsigned long long v = 0xDEADBEEFA55C0000ULL;
1183*598139dcSAndroid Build Coastguard Worker 
1184*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
1185*598139dcSAndroid Build Coastguard Worker 
1186*598139dcSAndroid Build Coastguard Worker     v += pid & 0xFFFF;
1187*598139dcSAndroid Build Coastguard Worker 
1188*598139dcSAndroid Build Coastguard Worker     // This test is racey; an event occurs between clear and dump.
1189*598139dcSAndroid Build Coastguard Worker     // We accept that we will get a false positive, but never a false negative.
1190*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(
1191*598139dcSAndroid Build Coastguard Worker         NULL !=
1192*598139dcSAndroid Build Coastguard Worker         (fp = popen("( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
1193*598139dcSAndroid Build Coastguard Worker                     " logcat -b events -c 2>&1 ;"
1194*598139dcSAndroid Build Coastguard Worker                     " logcat -b events -g 2>&1 ;"
1195*598139dcSAndroid Build Coastguard Worker                     " logcat -v brief -b events 2>&1",
1196*598139dcSAndroid Build Coastguard Worker                     "r")));
1197*598139dcSAndroid Build Coastguard Worker 
1198*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1199*598139dcSAndroid Build Coastguard Worker 
1200*598139dcSAndroid Build Coastguard Worker     int count = 0;
1201*598139dcSAndroid Build Coastguard Worker     int minus_g = 0;
1202*598139dcSAndroid Build Coastguard Worker 
1203*598139dcSAndroid Build Coastguard Worker     int signals = 0;
1204*598139dcSAndroid Build Coastguard Worker 
1205*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, caught_blocking_clear);
1206*598139dcSAndroid Build Coastguard Worker     alarm(2);
1207*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1208*598139dcSAndroid Build Coastguard Worker         if (!strncmp(buffer, "clearLog: ", strlen("clearLog: "))) {
1209*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
1210*598139dcSAndroid Build Coastguard Worker             count = signals = 1;
1211*598139dcSAndroid Build Coastguard Worker             break;
1212*598139dcSAndroid Build Coastguard Worker         }
1213*598139dcSAndroid Build Coastguard Worker         if (!strncmp(buffer, "failed to clear", strlen("failed to clear"))) {
1214*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
1215*598139dcSAndroid Build Coastguard Worker             count = signals = 1;
1216*598139dcSAndroid Build Coastguard Worker             break;
1217*598139dcSAndroid Build Coastguard Worker         }
1218*598139dcSAndroid Build Coastguard Worker 
1219*598139dcSAndroid Build Coastguard Worker         if (!strncmp(buffer, "DONE", 4)) {
1220*598139dcSAndroid Build Coastguard Worker             break;
1221*598139dcSAndroid Build Coastguard Worker         }
1222*598139dcSAndroid Build Coastguard Worker 
1223*598139dcSAndroid Build Coastguard Worker         int size, consumed, readable, max, payload;
1224*598139dcSAndroid Build Coastguard Worker         char size_mult[4], consumed_mult[4], readable_mult[4];
1225*598139dcSAndroid Build Coastguard Worker         size = consumed = max = payload = 0;
1226*598139dcSAndroid Build Coastguard Worker         if (8 == sscanf(buffer,
1227*598139dcSAndroid Build Coastguard Worker                         "events: ring buffer is %d %3s (%d %3s consumed, %d %3s readable),"
1228*598139dcSAndroid Build Coastguard Worker                         " max entry is %d B, max payload is %d B",
1229*598139dcSAndroid Build Coastguard Worker                         &size, size_mult, &consumed, consumed_mult, &readable, readable_mult, &max,
1230*598139dcSAndroid Build Coastguard Worker                         &payload)) {
1231*598139dcSAndroid Build Coastguard Worker             long full_size = size, full_consumed = consumed;
1232*598139dcSAndroid Build Coastguard Worker 
1233*598139dcSAndroid Build Coastguard Worker             switch (size_mult[0]) {
1234*598139dcSAndroid Build Coastguard Worker                 case 'G':
1235*598139dcSAndroid Build Coastguard Worker                     full_size *= 1024;
1236*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1237*598139dcSAndroid Build Coastguard Worker                 case 'M':
1238*598139dcSAndroid Build Coastguard Worker                     full_size *= 1024;
1239*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1240*598139dcSAndroid Build Coastguard Worker                 case 'K':
1241*598139dcSAndroid Build Coastguard Worker                     full_size *= 1024;
1242*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1243*598139dcSAndroid Build Coastguard Worker                 case 'B':
1244*598139dcSAndroid Build Coastguard Worker                     break;
1245*598139dcSAndroid Build Coastguard Worker             }
1246*598139dcSAndroid Build Coastguard Worker             switch (consumed_mult[0]) {
1247*598139dcSAndroid Build Coastguard Worker                 case 'G':
1248*598139dcSAndroid Build Coastguard Worker                     full_consumed *= 1024;
1249*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1250*598139dcSAndroid Build Coastguard Worker                 case 'M':
1251*598139dcSAndroid Build Coastguard Worker                     full_consumed *= 1024;
1252*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1253*598139dcSAndroid Build Coastguard Worker                 case 'K':
1254*598139dcSAndroid Build Coastguard Worker                     full_consumed *= 1024;
1255*598139dcSAndroid Build Coastguard Worker                     FALLTHROUGH_INTENDED;
1256*598139dcSAndroid Build Coastguard Worker                 case 'B':
1257*598139dcSAndroid Build Coastguard Worker                     break;
1258*598139dcSAndroid Build Coastguard Worker             }
1259*598139dcSAndroid Build Coastguard Worker             EXPECT_GT(full_size, full_consumed);
1260*598139dcSAndroid Build Coastguard Worker             EXPECT_GT(full_size, max);
1261*598139dcSAndroid Build Coastguard Worker             EXPECT_GT(max, payload);
1262*598139dcSAndroid Build Coastguard Worker             EXPECT_GT(max, full_consumed);
1263*598139dcSAndroid Build Coastguard Worker 
1264*598139dcSAndroid Build Coastguard Worker             ++minus_g;
1265*598139dcSAndroid Build Coastguard Worker             continue;
1266*598139dcSAndroid Build Coastguard Worker         }
1267*598139dcSAndroid Build Coastguard Worker 
1268*598139dcSAndroid Build Coastguard Worker         ++count;
1269*598139dcSAndroid Build Coastguard Worker 
1270*598139dcSAndroid Build Coastguard Worker         int p;
1271*598139dcSAndroid Build Coastguard Worker         unsigned long long l;
1272*598139dcSAndroid Build Coastguard Worker 
1273*598139dcSAndroid Build Coastguard Worker         if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l)) || (p != pid)) {
1274*598139dcSAndroid Build Coastguard Worker             continue;
1275*598139dcSAndroid Build Coastguard Worker         }
1276*598139dcSAndroid Build Coastguard Worker 
1277*598139dcSAndroid Build Coastguard Worker         if (l == v) {
1278*598139dcSAndroid Build Coastguard Worker             if (count > 1) {
1279*598139dcSAndroid Build Coastguard Worker                 fprintf(stderr, "WARNING: Possible false positive\n");
1280*598139dcSAndroid Build Coastguard Worker             }
1281*598139dcSAndroid Build Coastguard Worker             ++signals;
1282*598139dcSAndroid Build Coastguard Worker             break;
1283*598139dcSAndroid Build Coastguard Worker         }
1284*598139dcSAndroid Build Coastguard Worker     }
1285*598139dcSAndroid Build Coastguard Worker     alarm(0);
1286*598139dcSAndroid Build Coastguard Worker     signal(SIGALRM, SIG_DFL);
1287*598139dcSAndroid Build Coastguard Worker 
1288*598139dcSAndroid Build Coastguard Worker     // Generate SIGPIPE
1289*598139dcSAndroid Build Coastguard Worker     fclose(fp);
1290*598139dcSAndroid Build Coastguard Worker     caught_blocking_clear(0);
1291*598139dcSAndroid Build Coastguard Worker 
1292*598139dcSAndroid Build Coastguard Worker     pclose(fp);
1293*598139dcSAndroid Build Coastguard Worker 
1294*598139dcSAndroid Build Coastguard Worker     EXPECT_GE(count, 1);
1295*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(minus_g, 1);
1296*598139dcSAndroid Build Coastguard Worker 
1297*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(signals, 1);
1298*598139dcSAndroid Build Coastguard Worker }
1299*598139dcSAndroid Build Coastguard Worker #endif
1300*598139dcSAndroid Build Coastguard Worker 
get_prune_rules(char ** list)1301*598139dcSAndroid Build Coastguard Worker static bool get_prune_rules(char** list) {
1302*598139dcSAndroid Build Coastguard Worker     FILE* fp = popen(logcat_executable " -p 2>/dev/null", "r");
1303*598139dcSAndroid Build Coastguard Worker     if (fp == NULL) {
1304*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: logcat -p 2>/dev/null\n");
1305*598139dcSAndroid Build Coastguard Worker         return false;
1306*598139dcSAndroid Build Coastguard Worker     }
1307*598139dcSAndroid Build Coastguard Worker 
1308*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1309*598139dcSAndroid Build Coastguard Worker 
1310*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1311*598139dcSAndroid Build Coastguard Worker         char* hold = *list;
1312*598139dcSAndroid Build Coastguard Worker         char* buf = buffer;
1313*598139dcSAndroid Build Coastguard Worker         while (isspace(*buf)) {
1314*598139dcSAndroid Build Coastguard Worker             ++buf;
1315*598139dcSAndroid Build Coastguard Worker         }
1316*598139dcSAndroid Build Coastguard Worker         char* end = buf + strlen(buf);
1317*598139dcSAndroid Build Coastguard Worker         while (isspace(*--end) && (end >= buf)) {
1318*598139dcSAndroid Build Coastguard Worker             *end = '\0';
1319*598139dcSAndroid Build Coastguard Worker         }
1320*598139dcSAndroid Build Coastguard Worker         if (end < buf) {
1321*598139dcSAndroid Build Coastguard Worker             continue;
1322*598139dcSAndroid Build Coastguard Worker         }
1323*598139dcSAndroid Build Coastguard Worker         if (hold) {
1324*598139dcSAndroid Build Coastguard Worker             asprintf(list, "%s %s", hold, buf);
1325*598139dcSAndroid Build Coastguard Worker             free(hold);
1326*598139dcSAndroid Build Coastguard Worker         } else {
1327*598139dcSAndroid Build Coastguard Worker             asprintf(list, "%s", buf);
1328*598139dcSAndroid Build Coastguard Worker         }
1329*598139dcSAndroid Build Coastguard Worker     }
1330*598139dcSAndroid Build Coastguard Worker     pclose(fp);
1331*598139dcSAndroid Build Coastguard Worker     return *list != NULL;
1332*598139dcSAndroid Build Coastguard Worker }
1333*598139dcSAndroid Build Coastguard Worker 
set_prune_rules(const char * list)1334*598139dcSAndroid Build Coastguard Worker static bool set_prune_rules(const char* list) {
1335*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1336*598139dcSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer), logcat_executable " -P '%s' 2>&1",
1337*598139dcSAndroid Build Coastguard Worker              list ? list : "");
1338*598139dcSAndroid Build Coastguard Worker     FILE* fp = popen(buffer, "r");
1339*598139dcSAndroid Build Coastguard Worker     if (fp == NULL) {
1340*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: %s\n", buffer);
1341*598139dcSAndroid Build Coastguard Worker         return false;
1342*598139dcSAndroid Build Coastguard Worker     }
1343*598139dcSAndroid Build Coastguard Worker 
1344*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1345*598139dcSAndroid Build Coastguard Worker         char* buf = buffer;
1346*598139dcSAndroid Build Coastguard Worker         while (isspace(*buf)) {
1347*598139dcSAndroid Build Coastguard Worker             ++buf;
1348*598139dcSAndroid Build Coastguard Worker         }
1349*598139dcSAndroid Build Coastguard Worker         char* end = buf + strlen(buf);
1350*598139dcSAndroid Build Coastguard Worker         while ((end > buf) && isspace(*--end)) {
1351*598139dcSAndroid Build Coastguard Worker             *end = '\0';
1352*598139dcSAndroid Build Coastguard Worker         }
1353*598139dcSAndroid Build Coastguard Worker         if (end <= buf) {
1354*598139dcSAndroid Build Coastguard Worker             continue;
1355*598139dcSAndroid Build Coastguard Worker         }
1356*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "%s\n", buf);
1357*598139dcSAndroid Build Coastguard Worker         pclose(fp);
1358*598139dcSAndroid Build Coastguard Worker         return false;
1359*598139dcSAndroid Build Coastguard Worker     }
1360*598139dcSAndroid Build Coastguard Worker     return pclose(fp) == 0;
1361*598139dcSAndroid Build Coastguard Worker }
1362*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,prune_rules_adjust)1363*598139dcSAndroid Build Coastguard Worker TEST(logcat, prune_rules_adjust) {
1364*598139dcSAndroid Build Coastguard Worker     char* list = NULL;
1365*598139dcSAndroid Build Coastguard Worker     char* adjust = NULL;
1366*598139dcSAndroid Build Coastguard Worker 
1367*598139dcSAndroid Build Coastguard Worker     get_prune_rules(&list);
1368*598139dcSAndroid Build Coastguard Worker 
1369*598139dcSAndroid Build Coastguard Worker     static const char adjustment[] = "~! 300/20 300/25 2000 ~1000/5 ~1000/30";
1370*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(true, set_prune_rules(adjustment));
1371*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(true, get_prune_rules(&adjust));
1372*598139dcSAndroid Build Coastguard Worker     EXPECT_STREQ(adjustment, adjust);
1373*598139dcSAndroid Build Coastguard Worker     free(adjust);
1374*598139dcSAndroid Build Coastguard Worker     adjust = NULL;
1375*598139dcSAndroid Build Coastguard Worker 
1376*598139dcSAndroid Build Coastguard Worker     static const char adjustment2[] = "300/20 300/21 2000 ~1000";
1377*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(true, set_prune_rules(adjustment2));
1378*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(true, get_prune_rules(&adjust));
1379*598139dcSAndroid Build Coastguard Worker     EXPECT_STREQ(adjustment2, adjust);
1380*598139dcSAndroid Build Coastguard Worker     free(adjust);
1381*598139dcSAndroid Build Coastguard Worker     adjust = NULL;
1382*598139dcSAndroid Build Coastguard Worker 
1383*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(true, set_prune_rules(list));
1384*598139dcSAndroid Build Coastguard Worker     get_prune_rules(&adjust);
1385*598139dcSAndroid Build Coastguard Worker     EXPECT_STREQ(list ? list : "", adjust ? adjust : "");
1386*598139dcSAndroid Build Coastguard Worker     free(adjust);
1387*598139dcSAndroid Build Coastguard Worker     adjust = NULL;
1388*598139dcSAndroid Build Coastguard Worker 
1389*598139dcSAndroid Build Coastguard Worker     free(list);
1390*598139dcSAndroid Build Coastguard Worker     list = NULL;
1391*598139dcSAndroid Build Coastguard Worker }
1392*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,regex)1393*598139dcSAndroid Build Coastguard Worker TEST(logcat, regex) {
1394*598139dcSAndroid Build Coastguard Worker     FILE* fp;
1395*598139dcSAndroid Build Coastguard Worker     int count = 0;
1396*598139dcSAndroid Build Coastguard Worker 
1397*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1398*598139dcSAndroid Build Coastguard Worker #define logcat_regex_prefix logcat_executable "_test"
1399*598139dcSAndroid Build Coastguard Worker 
1400*598139dcSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer),
1401*598139dcSAndroid Build Coastguard Worker              logcat_executable " --pid %d -d -e " logcat_regex_prefix "_a+b",
1402*598139dcSAndroid Build Coastguard Worker              getpid());
1403*598139dcSAndroid Build Coastguard Worker 
1404*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_WARN, logcat_regex_prefix,
1405*598139dcSAndroid Build Coastguard Worker                                           logcat_regex_prefix "_ab"));
1406*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_WARN, logcat_regex_prefix,
1407*598139dcSAndroid Build Coastguard Worker                                           logcat_regex_prefix "_b"));
1408*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_WARN, logcat_regex_prefix,
1409*598139dcSAndroid Build Coastguard Worker                                           logcat_regex_prefix "_aaaab"));
1410*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_WARN, logcat_regex_prefix,
1411*598139dcSAndroid Build Coastguard Worker                                           logcat_regex_prefix "_aaaa"));
1412*598139dcSAndroid Build Coastguard Worker     // Let the logs settle
1413*598139dcSAndroid Build Coastguard Worker     rest();
1414*598139dcSAndroid Build Coastguard Worker 
1415*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
1416*598139dcSAndroid Build Coastguard Worker 
1417*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1418*598139dcSAndroid Build Coastguard Worker         if (!strncmp(begin, buffer, sizeof(begin) - 1)) {
1419*598139dcSAndroid Build Coastguard Worker             continue;
1420*598139dcSAndroid Build Coastguard Worker         }
1421*598139dcSAndroid Build Coastguard Worker 
1422*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(strstr(buffer, logcat_regex_prefix "_") != NULL);
1423*598139dcSAndroid Build Coastguard Worker 
1424*598139dcSAndroid Build Coastguard Worker         count++;
1425*598139dcSAndroid Build Coastguard Worker     }
1426*598139dcSAndroid Build Coastguard Worker 
1427*598139dcSAndroid Build Coastguard Worker     pclose(fp);
1428*598139dcSAndroid Build Coastguard Worker 
1429*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(2, count);
1430*598139dcSAndroid Build Coastguard Worker }
1431*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,maxcount)1432*598139dcSAndroid Build Coastguard Worker TEST(logcat, maxcount) {
1433*598139dcSAndroid Build Coastguard Worker     FILE* fp;
1434*598139dcSAndroid Build Coastguard Worker     int count = 0;
1435*598139dcSAndroid Build Coastguard Worker 
1436*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1437*598139dcSAndroid Build Coastguard Worker 
1438*598139dcSAndroid Build Coastguard Worker     snprintf(buffer, sizeof(buffer),
1439*598139dcSAndroid Build Coastguard Worker              logcat_executable " --pid %d -d --max-count 3", getpid());
1440*598139dcSAndroid Build Coastguard Worker 
1441*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(
1442*598139dcSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_WARN, "logcat_test", "logcat_test"));
1443*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(
1444*598139dcSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_WARN, "logcat_test", "logcat_test"));
1445*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(
1446*598139dcSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_WARN, "logcat_test", "logcat_test"));
1447*598139dcSAndroid Build Coastguard Worker     LOG_FAILURE_RETRY(
1448*598139dcSAndroid Build Coastguard Worker         __android_log_print(ANDROID_LOG_WARN, "logcat_test", "logcat_test"));
1449*598139dcSAndroid Build Coastguard Worker 
1450*598139dcSAndroid Build Coastguard Worker     rest();
1451*598139dcSAndroid Build Coastguard Worker 
1452*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
1453*598139dcSAndroid Build Coastguard Worker 
1454*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1455*598139dcSAndroid Build Coastguard Worker         if (!strncmp(begin, buffer, sizeof(begin) - 1)) {
1456*598139dcSAndroid Build Coastguard Worker             continue;
1457*598139dcSAndroid Build Coastguard Worker         }
1458*598139dcSAndroid Build Coastguard Worker 
1459*598139dcSAndroid Build Coastguard Worker         count++;
1460*598139dcSAndroid Build Coastguard Worker     }
1461*598139dcSAndroid Build Coastguard Worker 
1462*598139dcSAndroid Build Coastguard Worker     pclose(fp);
1463*598139dcSAndroid Build Coastguard Worker 
1464*598139dcSAndroid Build Coastguard Worker     ASSERT_EQ(3, count);
1465*598139dcSAndroid Build Coastguard Worker }
1466*598139dcSAndroid Build Coastguard Worker 
1467*598139dcSAndroid Build Coastguard Worker static bool End_to_End(const char* tag, const char* fmt, ...)
1468*598139dcSAndroid Build Coastguard Worker #if defined(__GNUC__)
1469*598139dcSAndroid Build Coastguard Worker     __attribute__((__format__(printf, 2, 3)))
1470*598139dcSAndroid Build Coastguard Worker #endif
1471*598139dcSAndroid Build Coastguard Worker     ;
1472*598139dcSAndroid Build Coastguard Worker 
End_to_End(const char * tag,const char * fmt,...)1473*598139dcSAndroid Build Coastguard Worker static bool End_to_End(const char* tag, const char* fmt, ...) {
1474*598139dcSAndroid Build Coastguard Worker     FILE* fp = popen(logcat_executable " -v brief -b events -v descriptive -t 100 2>/dev/null", "r");
1475*598139dcSAndroid Build Coastguard Worker     if (!fp) {
1476*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "End_to_End: popen failed");
1477*598139dcSAndroid Build Coastguard Worker         return false;
1478*598139dcSAndroid Build Coastguard Worker     }
1479*598139dcSAndroid Build Coastguard Worker 
1480*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1481*598139dcSAndroid Build Coastguard Worker     va_list ap;
1482*598139dcSAndroid Build Coastguard Worker 
1483*598139dcSAndroid Build Coastguard Worker     va_start(ap, fmt);
1484*598139dcSAndroid Build Coastguard Worker     vsnprintf(buffer, sizeof(buffer), fmt, ap);
1485*598139dcSAndroid Build Coastguard Worker     va_end(ap);
1486*598139dcSAndroid Build Coastguard Worker 
1487*598139dcSAndroid Build Coastguard Worker     char* str = NULL;
1488*598139dcSAndroid Build Coastguard Worker     asprintf(&str, "I/%s ( %%d):%%c%s%%c", tag, buffer);
1489*598139dcSAndroid Build Coastguard Worker     std::string expect(str);
1490*598139dcSAndroid Build Coastguard Worker     free(str);
1491*598139dcSAndroid Build Coastguard Worker 
1492*598139dcSAndroid Build Coastguard Worker     int count = 0;
1493*598139dcSAndroid Build Coastguard Worker     pid_t pid = getpid();
1494*598139dcSAndroid Build Coastguard Worker     std::string lastMatch;
1495*598139dcSAndroid Build Coastguard Worker     int maxMatch = 1;
1496*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp)) {
1497*598139dcSAndroid Build Coastguard Worker         char space;
1498*598139dcSAndroid Build Coastguard Worker         char newline;
1499*598139dcSAndroid Build Coastguard Worker         int p;
1500*598139dcSAndroid Build Coastguard Worker         int ret = sscanf(buffer, expect.c_str(), &p, &space, &newline);
1501*598139dcSAndroid Build Coastguard Worker         if ((ret == 3) && (p == pid) && (space == ' ') && (newline == '\n')) {
1502*598139dcSAndroid Build Coastguard Worker             ++count;
1503*598139dcSAndroid Build Coastguard Worker         } else if ((ret >= maxMatch) && (p == pid) && (count == 0)) {
1504*598139dcSAndroid Build Coastguard Worker             lastMatch = buffer;
1505*598139dcSAndroid Build Coastguard Worker             maxMatch = ret;
1506*598139dcSAndroid Build Coastguard Worker         }
1507*598139dcSAndroid Build Coastguard Worker     }
1508*598139dcSAndroid Build Coastguard Worker 
1509*598139dcSAndroid Build Coastguard Worker     pclose(fp);
1510*598139dcSAndroid Build Coastguard Worker 
1511*598139dcSAndroid Build Coastguard Worker     if ((count == 0) && (lastMatch.length() > 0)) {
1512*598139dcSAndroid Build Coastguard Worker         // Help us pinpoint where things went wrong ...
1513*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Closest match for\n    %s\n  is\n    %s",
1514*598139dcSAndroid Build Coastguard Worker                 expect.c_str(), lastMatch.c_str());
1515*598139dcSAndroid Build Coastguard Worker     } else if (count > 3) {
1516*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, "Too many matches (%d) for %s\n", count, expect.c_str());
1517*598139dcSAndroid Build Coastguard Worker     }
1518*598139dcSAndroid Build Coastguard Worker 
1519*598139dcSAndroid Build Coastguard Worker     // Three different known tests, we can see pollution from the others
1520*598139dcSAndroid Build Coastguard Worker     return count && (count <= 3);
1521*598139dcSAndroid Build Coastguard Worker }
1522*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,descriptive)1523*598139dcSAndroid Build Coastguard Worker TEST(logcat, descriptive) {
1524*598139dcSAndroid Build Coastguard Worker     struct tag {
1525*598139dcSAndroid Build Coastguard Worker         uint32_t tagNo;
1526*598139dcSAndroid Build Coastguard Worker         const char* tagStr;
1527*598139dcSAndroid Build Coastguard Worker     };
1528*598139dcSAndroid Build Coastguard Worker     int ret;
1529*598139dcSAndroid Build Coastguard Worker 
1530*598139dcSAndroid Build Coastguard Worker     {
1531*598139dcSAndroid Build Coastguard Worker         static const struct tag hhgtg = { 42, "answer" };
1532*598139dcSAndroid Build Coastguard Worker         android_log_event_list ctx(hhgtg.tagNo);
1533*598139dcSAndroid Build Coastguard Worker         static const char theAnswer[] = "what is five by seven";
1534*598139dcSAndroid Build Coastguard Worker         ctx << theAnswer;
1535*598139dcSAndroid Build Coastguard Worker         // crafted to rest at least once after, and rest between retries.
1536*598139dcSAndroid Build Coastguard Worker         for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1537*598139dcSAndroid Build Coastguard Worker         EXPECT_GE(ret, 0);
1538*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(
1539*598139dcSAndroid Build Coastguard Worker             End_to_End(hhgtg.tagStr, "to life the universe etc=%s", theAnswer));
1540*598139dcSAndroid Build Coastguard Worker     }
1541*598139dcSAndroid Build Coastguard Worker 
1542*598139dcSAndroid Build Coastguard Worker     {
1543*598139dcSAndroid Build Coastguard Worker         static const struct tag sync = { 2720, "sync" };
1544*598139dcSAndroid Build Coastguard Worker         static const char id[] = logcat_executable ".descriptive-sync";
1545*598139dcSAndroid Build Coastguard Worker         {
1546*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1547*598139dcSAndroid Build Coastguard Worker             ctx << id << (int32_t)42 << (int32_t)-1 << (int32_t)0;
1548*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1549*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1550*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr,
1551*598139dcSAndroid Build Coastguard Worker                                    "[id=%s,event=42,source=-1,account=0]", id));
1552*598139dcSAndroid Build Coastguard Worker         }
1553*598139dcSAndroid Build Coastguard Worker 
1554*598139dcSAndroid Build Coastguard Worker         // Partial match to description
1555*598139dcSAndroid Build Coastguard Worker         {
1556*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1557*598139dcSAndroid Build Coastguard Worker             ctx << id << (int32_t)43 << (int64_t)-1 << (int32_t)0;
1558*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1559*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1560*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "[id=%s,event=43,-1,0]", id));
1561*598139dcSAndroid Build Coastguard Worker         }
1562*598139dcSAndroid Build Coastguard Worker 
1563*598139dcSAndroid Build Coastguard Worker         // Negative Test of End_to_End, ensure it is working
1564*598139dcSAndroid Build Coastguard Worker         {
1565*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1566*598139dcSAndroid Build Coastguard Worker             ctx << id << (int32_t)44 << (int32_t)-1 << (int64_t)0;
1567*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1568*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1569*598139dcSAndroid Build Coastguard Worker             fprintf(stderr, "Expect a \"Closest match\" message\n");
1570*598139dcSAndroid Build Coastguard Worker             EXPECT_FALSE(End_to_End(
1571*598139dcSAndroid Build Coastguard Worker                 sync.tagStr, "[id=%s,event=44,source=-1,account=0]", id));
1572*598139dcSAndroid Build Coastguard Worker         }
1573*598139dcSAndroid Build Coastguard Worker     }
1574*598139dcSAndroid Build Coastguard Worker 
1575*598139dcSAndroid Build Coastguard Worker     {
1576*598139dcSAndroid Build Coastguard Worker         static const struct tag sync = { 2747, "contacts_aggregation" };
1577*598139dcSAndroid Build Coastguard Worker         {
1578*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1579*598139dcSAndroid Build Coastguard Worker             ctx << (uint64_t)30 << (int32_t)2;
1580*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1581*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1582*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(
1583*598139dcSAndroid Build Coastguard Worker                 End_to_End(sync.tagStr, "[aggregation time=30ms,count=2]"));
1584*598139dcSAndroid Build Coastguard Worker         }
1585*598139dcSAndroid Build Coastguard Worker 
1586*598139dcSAndroid Build Coastguard Worker         {
1587*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1588*598139dcSAndroid Build Coastguard Worker             ctx << (uint64_t)31570 << (int32_t)911;
1589*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1590*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1591*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(
1592*598139dcSAndroid Build Coastguard Worker                 End_to_End(sync.tagStr, "[aggregation time=31.57s,count=911]"));
1593*598139dcSAndroid Build Coastguard Worker         }
1594*598139dcSAndroid Build Coastguard Worker     }
1595*598139dcSAndroid Build Coastguard Worker 
1596*598139dcSAndroid Build Coastguard Worker     {
1597*598139dcSAndroid Build Coastguard Worker         static const struct tag sync = { 75000, "sqlite_mem_alarm_current" };
1598*598139dcSAndroid Build Coastguard Worker         {
1599*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1600*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)512;
1601*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1602*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1603*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=512B"));
1604*598139dcSAndroid Build Coastguard Worker         }
1605*598139dcSAndroid Build Coastguard Worker 
1606*598139dcSAndroid Build Coastguard Worker         {
1607*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1608*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)3072;
1609*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1610*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1611*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=3KB"));
1612*598139dcSAndroid Build Coastguard Worker         }
1613*598139dcSAndroid Build Coastguard Worker 
1614*598139dcSAndroid Build Coastguard Worker         {
1615*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1616*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)2097152;
1617*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1618*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1619*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=2MB"));
1620*598139dcSAndroid Build Coastguard Worker         }
1621*598139dcSAndroid Build Coastguard Worker 
1622*598139dcSAndroid Build Coastguard Worker         {
1623*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1624*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)2097153;
1625*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1626*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1627*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=2097153B"));
1628*598139dcSAndroid Build Coastguard Worker         }
1629*598139dcSAndroid Build Coastguard Worker 
1630*598139dcSAndroid Build Coastguard Worker         {
1631*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1632*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)1073741824;
1633*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1634*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1635*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=1GB"));
1636*598139dcSAndroid Build Coastguard Worker         }
1637*598139dcSAndroid Build Coastguard Worker 
1638*598139dcSAndroid Build Coastguard Worker         {
1639*598139dcSAndroid Build Coastguard Worker             android_log_event_list ctx(sync.tagNo);
1640*598139dcSAndroid Build Coastguard Worker             ctx << (uint32_t)3221225472;  // 3MB, but on purpose overflowed
1641*598139dcSAndroid Build Coastguard Worker             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1642*598139dcSAndroid Build Coastguard Worker             EXPECT_GE(ret, 0);
1643*598139dcSAndroid Build Coastguard Worker             EXPECT_TRUE(End_to_End(sync.tagStr, "current=-1GB"));
1644*598139dcSAndroid Build Coastguard Worker         }
1645*598139dcSAndroid Build Coastguard Worker     }
1646*598139dcSAndroid Build Coastguard Worker 
1647*598139dcSAndroid Build Coastguard Worker     {
1648*598139dcSAndroid Build Coastguard Worker         static const struct tag sync = { 27501, "notification_panel_hidden" };
1649*598139dcSAndroid Build Coastguard Worker         android_log_event_list ctx(sync.tagNo);
1650*598139dcSAndroid Build Coastguard Worker         for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
1651*598139dcSAndroid Build Coastguard Worker         EXPECT_GE(ret, 0);
1652*598139dcSAndroid Build Coastguard Worker         EXPECT_TRUE(End_to_End(sync.tagStr, ""));
1653*598139dcSAndroid Build Coastguard Worker     }
1654*598139dcSAndroid Build Coastguard Worker }
1655*598139dcSAndroid Build Coastguard Worker 
commandOutputSize(const char * command)1656*598139dcSAndroid Build Coastguard Worker static size_t commandOutputSize(const char* command) {
1657*598139dcSAndroid Build Coastguard Worker     FILE* fp = popen(command, "r");
1658*598139dcSAndroid Build Coastguard Worker     if (!fp) return 0;
1659*598139dcSAndroid Build Coastguard Worker 
1660*598139dcSAndroid Build Coastguard Worker     std::string ret;
1661*598139dcSAndroid Build Coastguard Worker     if (!android::base::ReadFdToString(fileno(fp), &ret)) return 0;
1662*598139dcSAndroid Build Coastguard Worker     if (pclose(fp) != 0) return 0;
1663*598139dcSAndroid Build Coastguard Worker 
1664*598139dcSAndroid Build Coastguard Worker     return ret.size();
1665*598139dcSAndroid Build Coastguard Worker }
1666*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,help)1667*598139dcSAndroid Build Coastguard Worker TEST(logcat, help) {
1668*598139dcSAndroid Build Coastguard Worker     size_t logcatHelpTextSize = commandOutputSize(logcat_executable " -h 2>&1");
1669*598139dcSAndroid Build Coastguard Worker     EXPECT_GT(logcatHelpTextSize, 4096UL);
1670*598139dcSAndroid Build Coastguard Worker     size_t logcatLastHelpTextSize =
1671*598139dcSAndroid Build Coastguard Worker         commandOutputSize(logcat_executable " -L -h 2>&1");
1672*598139dcSAndroid Build Coastguard Worker #ifdef USING_LOGCAT_EXECUTABLE_DEFAULT
1673*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(logcatHelpTextSize, logcatLastHelpTextSize);
1674*598139dcSAndroid Build Coastguard Worker #else
1675*598139dcSAndroid Build Coastguard Worker     // logcatd -L -h prints the help twice, as designed.
1676*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(logcatHelpTextSize * 2, logcatLastHelpTextSize);
1677*598139dcSAndroid Build Coastguard Worker #endif
1678*598139dcSAndroid Build Coastguard Worker }
1679*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,invalid_buffer)1680*598139dcSAndroid Build Coastguard Worker TEST(logcat, invalid_buffer) {
1681*598139dcSAndroid Build Coastguard Worker   FILE* fp = popen("logcat -b foo 2>&1", "r");
1682*598139dcSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, fp);
1683*598139dcSAndroid Build Coastguard Worker   std::string output;
1684*598139dcSAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFdToString(fileno(fp), &output));
1685*598139dcSAndroid Build Coastguard Worker   pclose(fp);
1686*598139dcSAndroid Build Coastguard Worker 
1687*598139dcSAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, output.find("Unknown buffer 'foo'"));
1688*598139dcSAndroid Build Coastguard Worker }
1689*598139dcSAndroid Build Coastguard Worker 
SniffUid(const std::string & line,uid_t & uid)1690*598139dcSAndroid Build Coastguard Worker static void SniffUid(const std::string& line, uid_t& uid) {
1691*598139dcSAndroid Build Coastguard Worker     auto uid_regex = std::regex{"\\S+\\s+\\S+\\s+(\\S+).*"};
1692*598139dcSAndroid Build Coastguard Worker 
1693*598139dcSAndroid Build Coastguard Worker     auto trimmed_line = android::base::Trim(line);
1694*598139dcSAndroid Build Coastguard Worker 
1695*598139dcSAndroid Build Coastguard Worker     std::smatch match_results;
1696*598139dcSAndroid Build Coastguard Worker     ASSERT_TRUE(std::regex_match(trimmed_line, match_results, uid_regex))
1697*598139dcSAndroid Build Coastguard Worker             << "Unable to find UID in line '" << trimmed_line << "'";
1698*598139dcSAndroid Build Coastguard Worker     auto uid_string = match_results[1];
1699*598139dcSAndroid Build Coastguard Worker     if (!android::base::ParseUint(uid_string, &uid)) {
1700*598139dcSAndroid Build Coastguard Worker         auto pwd = getpwnam(uid_string.str().c_str());
1701*598139dcSAndroid Build Coastguard Worker         ASSERT_NE(nullptr, pwd) << "uid '" << uid_string << "' in line '" << trimmed_line << "'";
1702*598139dcSAndroid Build Coastguard Worker         uid = pwd->pw_uid;
1703*598139dcSAndroid Build Coastguard Worker     }
1704*598139dcSAndroid Build Coastguard Worker }
1705*598139dcSAndroid Build Coastguard Worker 
UidsInLog(std::optional<std::vector<uid_t>> filter_uid,std::map<uid_t,size_t> & uids)1706*598139dcSAndroid Build Coastguard Worker static void UidsInLog(std::optional<std::vector<uid_t>> filter_uid, std::map<uid_t, size_t>& uids) {
1707*598139dcSAndroid Build Coastguard Worker     std::string command;
1708*598139dcSAndroid Build Coastguard Worker     if (filter_uid) {
1709*598139dcSAndroid Build Coastguard Worker         std::vector<std::string> uid_strings;
1710*598139dcSAndroid Build Coastguard Worker         for (const auto& uid : *filter_uid) {
1711*598139dcSAndroid Build Coastguard Worker             uid_strings.emplace_back(std::to_string(uid));
1712*598139dcSAndroid Build Coastguard Worker         }
1713*598139dcSAndroid Build Coastguard Worker         command = android::base::StringPrintf(logcat_executable
1714*598139dcSAndroid Build Coastguard Worker                                               " -v uid -b all -d 2>/dev/null --uid=%s",
1715*598139dcSAndroid Build Coastguard Worker                                               android::base::Join(uid_strings, ",").c_str());
1716*598139dcSAndroid Build Coastguard Worker     } else {
1717*598139dcSAndroid Build Coastguard Worker         command = logcat_executable " -v uid -b all -d 2>/dev/null";
1718*598139dcSAndroid Build Coastguard Worker     }
1719*598139dcSAndroid Build Coastguard Worker     auto fp = std::unique_ptr<FILE, decltype(&pclose)>(popen(command.c_str(), "r"), pclose);
1720*598139dcSAndroid Build Coastguard Worker     ASSERT_NE(nullptr, fp);
1721*598139dcSAndroid Build Coastguard Worker 
1722*598139dcSAndroid Build Coastguard Worker     char buffer[BIG_BUFFER];
1723*598139dcSAndroid Build Coastguard Worker     while (fgets(buffer, sizeof(buffer), fp.get())) {
1724*598139dcSAndroid Build Coastguard Worker         // Ignore dividers, e.g. '--------- beginning of radio'
1725*598139dcSAndroid Build Coastguard Worker         if (android::base::StartsWith(buffer, "---------")) {
1726*598139dcSAndroid Build Coastguard Worker             continue;
1727*598139dcSAndroid Build Coastguard Worker         }
1728*598139dcSAndroid Build Coastguard Worker         uid_t uid;
1729*598139dcSAndroid Build Coastguard Worker         SniffUid(buffer, uid);
1730*598139dcSAndroid Build Coastguard Worker         uids[uid]++;
1731*598139dcSAndroid Build Coastguard Worker     }
1732*598139dcSAndroid Build Coastguard Worker }
1733*598139dcSAndroid Build Coastguard Worker 
TopTwoInMap(const std::map<uid_t,size_t> & uids)1734*598139dcSAndroid Build Coastguard Worker static std::vector<uid_t> TopTwoInMap(const std::map<uid_t, size_t>& uids) {
1735*598139dcSAndroid Build Coastguard Worker     std::pair<uid_t, size_t> top = {0, 0};
1736*598139dcSAndroid Build Coastguard Worker     std::pair<uid_t, size_t> second = {0, 0};
1737*598139dcSAndroid Build Coastguard Worker     for (const auto& [uid, count] : uids) {
1738*598139dcSAndroid Build Coastguard Worker         if (count > top.second) {
1739*598139dcSAndroid Build Coastguard Worker             top = second;
1740*598139dcSAndroid Build Coastguard Worker             top = {uid, count};
1741*598139dcSAndroid Build Coastguard Worker         } else if (count > second.second) {
1742*598139dcSAndroid Build Coastguard Worker             second = {uid, count};
1743*598139dcSAndroid Build Coastguard Worker         }
1744*598139dcSAndroid Build Coastguard Worker     }
1745*598139dcSAndroid Build Coastguard Worker     return {top.first, second.first};
1746*598139dcSAndroid Build Coastguard Worker }
1747*598139dcSAndroid Build Coastguard Worker 
TEST(logcat,uid_filter)1748*598139dcSAndroid Build Coastguard Worker TEST(logcat, uid_filter) {
1749*598139dcSAndroid Build Coastguard Worker     std::map<uid_t, size_t> uids;
1750*598139dcSAndroid Build Coastguard Worker     UidsInLog({}, uids);
1751*598139dcSAndroid Build Coastguard Worker 
1752*598139dcSAndroid Build Coastguard Worker     ASSERT_GT(uids.size(), 2U);
1753*598139dcSAndroid Build Coastguard Worker     auto top_uids = TopTwoInMap(uids);
1754*598139dcSAndroid Build Coastguard Worker 
1755*598139dcSAndroid Build Coastguard Worker     // Test filtering with --uid=<top uid>
1756*598139dcSAndroid Build Coastguard Worker     std::map<uid_t, size_t> uids_only_top;
1757*598139dcSAndroid Build Coastguard Worker     std::vector<uid_t> top_uid = {top_uids[0]};
1758*598139dcSAndroid Build Coastguard Worker     UidsInLog(top_uid, uids_only_top);
1759*598139dcSAndroid Build Coastguard Worker 
1760*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(1U, uids_only_top.size());
1761*598139dcSAndroid Build Coastguard Worker 
1762*598139dcSAndroid Build Coastguard Worker     // Test filtering with --uid=<top uid>,<2nd top uid>
1763*598139dcSAndroid Build Coastguard Worker     std::map<uid_t, size_t> uids_only_top2;
1764*598139dcSAndroid Build Coastguard Worker     std::vector<uid_t> top2_uids = {top_uids[0], top_uids[1]};
1765*598139dcSAndroid Build Coastguard Worker     UidsInLog(top2_uids, uids_only_top2);
1766*598139dcSAndroid Build Coastguard Worker 
1767*598139dcSAndroid Build Coastguard Worker     EXPECT_EQ(2U, uids_only_top2.size());
1768*598139dcSAndroid Build Coastguard Worker }
1769