logcat_test.cpp revision 5d3d1f17dbcb01aedd510b5435ebdaf1d6afc138
1/* 2 * Copyright (C) 2013-2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <signal.h> 18#include <stdio.h> 19#include <gtest/gtest.h> 20#include <log/log.h> 21#include <log/logger.h> 22#include <log/log_read.h> 23 24// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and 25// non-syscall libs. Since we are only using this in the emergency of 26// a signal to stuff a terminating code into the logs, we will spin rather 27// than try a usleep. 28#define LOG_FAILURE_RETRY(exp) ({ \ 29 typeof (exp) _rc; \ 30 do { \ 31 _rc = (exp); \ 32 } while (((_rc == -1) \ 33 && ((errno == EINTR) \ 34 || (errno == EAGAIN))) \ 35 || (_rc == -EINTR) \ 36 || (_rc == -EAGAIN)); \ 37 _rc; }) 38 39static const char begin[] = "--------- beginning of "; 40 41TEST(logcat, sorted_order) { 42 FILE *fp; 43 44 ASSERT_EQ(0, NULL == (fp = popen( 45 "logcat -v time -b radio -b events -b system -b main -d 2>/dev/null", 46 "r"))); 47 48 class timestamp { 49 private: 50 int month; 51 int day; 52 int hour; 53 int minute; 54 int second; 55 int millisecond; 56 bool ok; 57 58 public: 59 void init(const char *buffer) 60 { 61 ok = false; 62 if (buffer != NULL) { 63 ok = sscanf(buffer, "%d-%d %d:%d:%d.%d ", 64 &month, &day, &hour, &minute, &second, &millisecond) == 6; 65 } 66 } 67 68 timestamp(const char *buffer) 69 { 70 init(buffer); 71 } 72 73 bool operator< (timestamp &T) 74 { 75 return !ok || !T.ok 76 || (month < T.month) 77 || ((month == T.month) 78 && ((day < T.day) 79 || ((day == T.day) 80 && ((hour < T.hour) 81 || ((hour == T.hour) 82 && ((minute < T.minute) 83 || ((minute == T.minute) 84 && ((second < T.second) 85 || ((second == T.second) 86 && (millisecond < T.millisecond)))))))))); 87 } 88 89 bool valid(void) 90 { 91 return ok; 92 } 93 } last(NULL); 94 95 char buffer[5120]; 96 97 int count = 0; 98 99 while (fgets(buffer, sizeof(buffer), fp)) { 100 if (!strncmp(begin, buffer, sizeof(begin) - 1)) { 101 continue; 102 } 103 if (!last.valid()) { 104 last.init(buffer); 105 } 106 timestamp next(buffer); 107 ASSERT_EQ(0, next < last); 108 if (next.valid()) { 109 last.init(buffer); 110 } 111 ++count; 112 } 113 114 pclose(fp); 115 116 ASSERT_LT(100, count); 117} 118 119TEST(logcat, buckets) { 120 FILE *fp; 121 122 ASSERT_EQ(0, NULL == (fp = popen( 123 "logcat -b radio -b events -b system -b main -d 2>/dev/null", 124 "r"))); 125 126 char buffer[5120]; 127 128 int ids = 0; 129 int count = 0; 130 131 while (fgets(buffer, sizeof(buffer), fp)) { 132 if (!strncmp(begin, buffer, sizeof(begin) - 1)) { 133 while (char *cp = strrchr(buffer, '\n')) { 134 *cp = '\0'; 135 } 136 log_id_t id = android_name_to_log_id(buffer + sizeof(begin) - 1); 137 ids |= 1 << id; 138 ++count; 139 } 140 } 141 142 pclose(fp); 143 144 ASSERT_EQ(15, ids); 145 146 ASSERT_EQ(4, count); 147} 148 149TEST(logcat, tail_3) { 150 FILE *fp; 151 152 ASSERT_EQ(0, NULL == (fp = popen( 153 "logcat -v long -b radio -b events -b system -b main -t 3 2>/dev/null", 154 "r"))); 155 156 char buffer[5120]; 157 158 int count = 0; 159 160 while (fgets(buffer, sizeof(buffer), fp)) { 161 if ((buffer[0] == '[') && (buffer[1] == ' ') 162 && isdigit(buffer[2]) && isdigit(buffer[3]) 163 && (buffer[4] == '-')) { 164 ++count; 165 } 166 } 167 168 pclose(fp); 169 170 ASSERT_EQ(3, count); 171} 172 173TEST(logcat, tail_10) { 174 FILE *fp; 175 176 ASSERT_EQ(0, NULL == (fp = popen( 177 "logcat -v long -b radio -b events -b system -b main -t 10 2>/dev/null", 178 "r"))); 179 180 char buffer[5120]; 181 182 int count = 0; 183 184 while (fgets(buffer, sizeof(buffer), fp)) { 185 if ((buffer[0] == '[') && (buffer[1] == ' ') 186 && isdigit(buffer[2]) && isdigit(buffer[3]) 187 && (buffer[4] == '-')) { 188 ++count; 189 } 190 } 191 192 pclose(fp); 193 194 ASSERT_EQ(10, count); 195} 196 197TEST(logcat, tail_100) { 198 FILE *fp; 199 200 ASSERT_EQ(0, NULL == (fp = popen( 201 "logcat -v long -b radio -b events -b system -b main -t 100 2>/dev/null", 202 "r"))); 203 204 char buffer[5120]; 205 206 int count = 0; 207 208 while (fgets(buffer, sizeof(buffer), fp)) { 209 if ((buffer[0] == '[') && (buffer[1] == ' ') 210 && isdigit(buffer[2]) && isdigit(buffer[3]) 211 && (buffer[4] == '-')) { 212 ++count; 213 } 214 } 215 216 pclose(fp); 217 218 ASSERT_EQ(100, count); 219} 220 221TEST(logcat, tail_1000) { 222 FILE *fp; 223 224 ASSERT_EQ(0, NULL == (fp = popen( 225 "logcat -v long -b radio -b events -b system -b main -t 1000 2>/dev/null", 226 "r"))); 227 228 char buffer[5120]; 229 230 int count = 0; 231 232 while (fgets(buffer, sizeof(buffer), fp)) { 233 if ((buffer[0] == '[') && (buffer[1] == ' ') 234 && isdigit(buffer[2]) && isdigit(buffer[3]) 235 && (buffer[4] == '-')) { 236 ++count; 237 } 238 } 239 240 pclose(fp); 241 242 ASSERT_EQ(1000, count); 243} 244 245TEST(logcat, End_to_End) { 246 pid_t pid = getpid(); 247 248 log_time ts(CLOCK_MONOTONIC); 249 250 ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); 251 252 FILE *fp; 253 ASSERT_EQ(0, NULL == (fp = popen( 254 "logcat -b events -t 100 2>/dev/null", 255 "r"))); 256 257 char buffer[5120]; 258 259 int count = 0; 260 261 while (fgets(buffer, sizeof(buffer), fp)) { 262 int p; 263 unsigned long long t; 264 265 if ((2 != sscanf(buffer, "I/[0] ( %d): %llu", &p, &t)) 266 || (p != pid)) { 267 continue; 268 } 269 270 log_time tx((const char *) &t); 271 if (ts == tx) { 272 ++count; 273 } 274 } 275 276 pclose(fp); 277 278 ASSERT_EQ(1, count); 279} 280 281TEST(logcat, get_) { 282 FILE *fp; 283 284 ASSERT_EQ(0, NULL == (fp = popen( 285 "logcat -b radio -b events -b system -b main -g 2>/dev/null", 286 "r"))); 287 288 char buffer[5120]; 289 290 int count = 0; 291 292 while (fgets(buffer, sizeof(buffer), fp)) { 293 int size, consumed, max, payload; 294 295 size = consumed = max = payload = 0; 296 if ((4 == sscanf(buffer, "%*s ring buffer is %dKb (%dKb consumed)," 297 " max entry is %db, max payload is %db", 298 &size, &consumed, &max, &payload)) 299 && ((size * 3) >= consumed) 300 && ((size * 1024) > max) 301 && (max > payload)) { 302 ++count; 303 } 304 } 305 306 pclose(fp); 307 308 ASSERT_EQ(4, count); 309} 310 311static void caught_blocking(int signum) 312{ 313 unsigned long long v = 0xDEADBEEFA55A0000ULL; 314 315 v += getpid() & 0xFFFF; 316 317 LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v))); 318} 319 320TEST(logcat, blocking) { 321 FILE *fp; 322 unsigned long long v = 0xDEADBEEFA55A0000ULL; 323 324 pid_t pid = getpid(); 325 326 v += pid & 0xFFFF; 327 328 ASSERT_EQ(0, NULL == (fp = popen( 329 "( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&" 330 " logcat -b events 2>&1", 331 "r"))); 332 333 char buffer[5120]; 334 335 int count = 0; 336 337 int signals = 0; 338 339 signal(SIGALRM, caught_blocking); 340 alarm(2); 341 while (fgets(buffer, sizeof(buffer), fp)) { 342 alarm(2); 343 344 ++count; 345 346 if (!strncmp(buffer, "DONE", 4)) { 347 break; 348 } 349 350 int p; 351 unsigned long long l; 352 353 if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l)) 354 || (p != pid)) { 355 continue; 356 } 357 358 if (l == v) { 359 ++signals; 360 break; 361 } 362 } 363 alarm(0); 364 signal(SIGALRM, SIG_DFL); 365 366 // Generate SIGPIPE 367 fclose(fp); 368 caught_blocking(0); 369 370 pclose(fp); 371 372 ASSERT_LT(10, count); 373 374 ASSERT_EQ(1, signals); 375} 376 377static void caught_blocking_tail(int signum) 378{ 379 unsigned long long v = 0xA55ADEADBEEF0000ULL; 380 381 v += getpid() & 0xFFFF; 382 383 LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v))); 384} 385 386TEST(logcat, blocking_tail) { 387 FILE *fp; 388 unsigned long long v = 0xA55ADEADBEEF0000ULL; 389 390 pid_t pid = getpid(); 391 392 v += pid & 0xFFFF; 393 394 ASSERT_EQ(0, NULL == (fp = popen( 395 "( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&" 396 " logcat -b events -T 5 2>&1", 397 "r"))); 398 399 char buffer[5120]; 400 401 int count = 0; 402 403 int signals = 0; 404 405 signal(SIGALRM, caught_blocking_tail); 406 alarm(2); 407 while (fgets(buffer, sizeof(buffer), fp)) { 408 alarm(2); 409 410 ++count; 411 412 if (!strncmp(buffer, "DONE", 4)) { 413 break; 414 } 415 416 int p; 417 unsigned long long l; 418 419 if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l)) 420 || (p != pid)) { 421 continue; 422 } 423 424 if (l == v) { 425 if (count >= 5) { 426 ++signals; 427 } 428 break; 429 } 430 } 431 alarm(0); 432 signal(SIGALRM, SIG_DFL); 433 434 /* Generate SIGPIPE */ 435 fclose(fp); 436 caught_blocking_tail(0); 437 438 pclose(fp); 439 440 ASSERT_LT(5, count); 441 442 ASSERT_EQ(1, signals); 443} 444