logcat_test.cpp 52 KB

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