Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2011 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 package com.android.loganalysis.parser;
     17 
     18 import com.android.loganalysis.item.BugreportItem;
     19 import com.android.loganalysis.item.IItem;
     20 import com.android.loganalysis.item.MiscKernelLogItem;
     21 import com.android.loganalysis.util.ArrayUtil;
     22 
     23 import junit.framework.TestCase;
     24 
     25 import java.text.DateFormat;
     26 import java.text.ParseException;
     27 import java.text.SimpleDateFormat;
     28 import java.util.Arrays;
     29 import java.util.Date;
     30 import java.util.List;
     31 
     32 /**
     33  * Unit tests for {@link BugreportParser}
     34  */
     35 public class BugreportParserTest extends TestCase {
     36 
     37     /**
     38      * Test that a bugreport can be parsed.
     39      */
     40     public void testParse() throws ParseException {
     41         List<String> lines =
     42                 Arrays.asList(
     43                         "========================================================",
     44                         "== dumpstate: 2012-04-25 20:45:10",
     45                         "========================================================",
     46                         "------ SECTION ------",
     47                         "",
     48                         "------ MEMORY INFO (/proc/meminfo) ------",
     49                         "MemTotal:         353332 kB",
     50                         "MemFree:           65420 kB",
     51                         "Buffers:           20800 kB",
     52                         "Cached:            86204 kB",
     53                         "SwapCached:            0 kB",
     54                         "",
     55                         "------ CPU INFO (top -n 1 -d 1 -m 30 -t) ------",
     56                         "",
     57                         "User 3%, System 3%, IOW 0%, IRQ 0%",
     58                         "User 33 + Nice 0 + Sys 32 + Idle 929 + IOW 0 + IRQ 0 + SIRQ 0 = 994",
     59                         "",
     60                         "------ PROCRANK (procrank) ------",
     61                         "  PID      Vss      Rss      Pss      Uss  cmdline",
     62                         "  178   87136K   81684K   52829K   50012K  system_server",
     63                         " 1313   78128K   77996K   48603K   45812K  com.google.android.apps.maps",
     64                         " 3247   61652K   61492K   33122K   30972K  com.android.browser",
     65                         "                          ------   ------  ------",
     66                         "                          203624K  163604K  TOTAL",
     67                         "RAM: 731448K total, 415804K free, 9016K buffers, 108548K cached",
     68                         "[procrank: 1.6s elapsed]",
     69                         "",
     70                         "------ KERNEL LOG (dmesg) ------",
     71                         "<6>[    0.000000] Initializing cgroup subsys cpu",
     72                         "<3>[    1.000000] benign message",
     73                         "",
     74                         "",
     75                         "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
     76                         "04-25 09:55:47.799  3064  3082 E AndroidRuntime: java.lang.Exception",
     77                         "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method1(Class.java:1)",
     78                         "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method2(Class.java:2)",
     79                         "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method3(Class.java:3)",
     80                         "04-25 17:17:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
     81                         "04-25 17:17:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
     82                         "04-25 17:17:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
     83                         "04-25 17:17:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
     84                         "04-25 18:33:27.273   115   115 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***",
     85                         "04-25 18:33:27.273   115   115 I DEBUG   : Build fingerprint: 'product:build:target'",
     86                         "04-25 18:33:27.273   115   115 I DEBUG   : pid: 3112, tid: 3112  >>> com.google.android.browser <<<",
     87                         "04-25 18:33:27.273   115   115 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000",
     88                         "",
     89                         "------ SYSTEM PROPERTIES ------",
     90                         "[dalvik.vm.dexopt-flags]: [m=y]",
     91                         "[dalvik.vm.heapgrowthlimit]: [48m]",
     92                         "[dalvik.vm.heapsize]: [256m]",
     93                         "[gsm.version.ril-impl]: [android moto-ril-multimode 1.0]",
     94                         "",
     95                         "------ LAST KMSG (/proc/last_kmsg) ------",
     96                         "[    0.000000] Initializing cgroup subsys cpu",
     97                         "[   16.203491] benign message",
     98                         "",
     99                         "------ SECTION ------",
    100                         "",
    101                         "------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2012-04-25 17:17:08) ------",
    102                         "",
    103                         "",
    104                         "----- pid 2887 at 2012-04-25 17:17:08 -----",
    105                         "Cmd line: com.android.package",
    106                         "",
    107                         "DALVIK THREADS:",
    108                         "(mutexes: tll=0 tsl=0 tscl=0 ghl=0)",
    109                         "",
    110                         "\"main\" prio=5 tid=1 SUSPENDED",
    111                         "  | group=\"main\" sCount=1 dsCount=0 obj=0x00000001 self=0x00000001",
    112                         "  | sysTid=2887 nice=0 sched=0/0 cgrp=foreground handle=0000000001",
    113                         "  | schedstat=( 0 0 0 ) utm=5954 stm=1017 core=0",
    114                         "  at class.method1(Class.java:1)",
    115                         "  at class.method2(Class.java:2)",
    116                         "  at class.method2(Class.java:2)",
    117                         "",
    118                         "----- end 2887 -----",
    119                         "",
    120                         "------ SECTION ------",
    121                         "",
    122                         "------ DUMPSYS (dumpsys) ------",
    123                         "DUMP OF SERVICE batterystats:",
    124                         "Battery History (0% used, 1636 used of 256KB, 15 strings using 794):",
    125                         "    0 (15) RESET:TIME: 1970-01-10-06-23-28",
    126                         "          +45s702ms (2) 001 80080000 volt=4187",
    127                         "          +1m15s525ms (2) 001 80080000 temp=299 volt=4155",
    128                         "Statistics since last charged:",
    129                         "  Time on battery: 1h 5m 2s 4ms (9%) realtime, 1h 5m 2s 4ms (9%) uptime",
    130                         " Time on battery screen off: 1h 4m 5s 8ms (9%) realtime, 1h 4m 5s 8ms (9%) uptime",
    131                         " All kernel wake locks:",
    132                         " Kernel Wake lock PowerManagerService.WakeLocks: 5m 10s 6ms (2 times) realtime",
    133                         " Kernel Wake lock msm_serial_hs_rx: 2m 13s 612ms (258 times) realtime",
    134                         "",
    135                         "  All partial wake locks:",
    136                         "  Wake lock 1001 ProxyController: 1h 4m 47s 565ms (4 times) realtime",
    137                         "  Wake lock 1013 AudioMix: 1s 979ms (3 times) realtime",
    138                         "",
    139                         "  All wakeup reasons:",
    140                         "  Wakeup reason 2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio: 1m 5s 4ms (2 times) realtime",
    141                         "  Wakeup reason 2:qcom,smd-rpm:2:fc4c.qcom,spmi: 7m 1s 914ms (7 times) realtime",
    142                         "",
    143                         "DUMP OF SERVICE package:",
    144                         "Package [com.google.android.calculator] (e075c9d):",
    145                         "  userId=10071",
    146                         "  secondaryCpuAbi=null",
    147                         "  versionCode=73000302 minSdk=10000 targetSdk=10000",
    148                         "  versionName=7.3 (3821978)",
    149                         "  splits=[base]",
    150                         "========================================================",
    151                         "== Running Application Services",
    152                         "========================================================",
    153                         "------ APP SERVICES (dumpsys activity service all) ------",
    154                         "SERVICE com.google.android.gms/"
    155                                 + "com.google.android.location.internal.GoogleLocationManagerService f4c9d pid=14",
    156                         " Location Request History By Package:",
    157                         "Interval effective/min/max 1/0/0[s] Duration: 140[minutes] ["
    158                                 + "com.google.android.gms, PRIORITY_NO_POWER, UserLocationProducer] "
    159                                 + "Num requests: 2 Active: true",
    160                         "Interval effective/min/max 284/285/3600[s] Duration: 140[minutes] "
    161                                 + "[com.google.android.googlequicksearchbox, PRIORITY_BALANCED_POWER_ACCURACY] "
    162                                 + "Num requests: 5 Active: true");
    163 
    164         BugreportItem bugreport = new BugreportParser().parse(lines);
    165         assertNotNull(bugreport);
    166         assertEquals(parseTime("2012-04-25 20:45:10.000"), bugreport.getTime());
    167 
    168         assertNotNull(bugreport.getMemInfo());
    169         assertEquals(5, bugreport.getMemInfo().size());
    170 
    171         assertNotNull(bugreport.getTop());
    172         assertEquals(994, bugreport.getTop().getTotal());
    173 
    174         assertNotNull(bugreport.getProcrank());
    175         assertEquals(3, bugreport.getProcrank().getPids().size());
    176 
    177         assertNotNull(bugreport.getKernelLog());
    178         assertEquals(1.0, bugreport.getKernelLog().getStopTime(), 0.000005);
    179 
    180         assertNotNull(bugreport.getSystemLog());
    181         assertEquals(parseTime("2012-04-25 09:55:47.799"), bugreport.getSystemLog().getStartTime());
    182         assertEquals(parseTime("2012-04-25 18:33:27.273"), bugreport.getSystemLog().getStopTime());
    183         assertEquals(3, bugreport.getSystemLog().getEvents().size());
    184         assertEquals(1, bugreport.getSystemLog().getAnrs().size());
    185         assertNotNull(bugreport.getSystemLog().getAnrs().get(0).getTrace());
    186 
    187         assertNotNull(bugreport.getLastKmsg());
    188         assertEquals(16.203491, bugreport.getLastKmsg().getStopTime(), 0.000005);
    189 
    190         assertNotNull(bugreport.getSystemProps());
    191         assertEquals(4, bugreport.getSystemProps().size());
    192 
    193         assertNotNull(bugreport.getDumpsys());
    194         assertNotNull(bugreport.getDumpsys().getBatteryStats());
    195         assertNotNull(bugreport.getDumpsys().getPackageStats());
    196 
    197         assertNotNull(bugreport.getActivityService());
    198         assertNotNull(bugreport.getActivityService().getLocationDumps().getLocationClients());
    199         assertEquals(bugreport.getActivityService().getLocationDumps().getLocationClients().size(),
    200                 2);
    201     }
    202 
    203     /**
    204      * Test that the logcat year is set correctly from the bugreport timestamp.
    205      */
    206     public void testParse_set_logcat_year() throws ParseException {
    207         List<String> lines = Arrays.asList(
    208                 "========================================================",
    209                 "== dumpstate: 1999-01-01 02:03:04",
    210                 "========================================================",
    211                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    212                 "01-01 01:02:03.000     1     1 I TAG     : message",
    213                 "01-01 01:02:04.000     1     1 I TAG     : message",
    214                 "");
    215 
    216         BugreportItem bugreport = new BugreportParser().parse(lines);
    217         assertNotNull(bugreport);
    218         assertEquals(parseTime("1999-01-01 02:03:04.000"), bugreport.getTime());
    219         assertNotNull(bugreport.getSystemLog());
    220         assertEquals(parseTime("1999-01-01 01:02:03.000"), bugreport.getSystemLog().getStartTime());
    221         assertEquals(parseTime("1999-01-01 01:02:04.000"), bugreport.getSystemLog().getStopTime());
    222     }
    223 
    224     /**
    225      * Test that the command line is parsed
    226      */
    227     public void testParse_command_line() {
    228         List<String> lines = Arrays.asList("Command line:");
    229         BugreportItem bugreport = new BugreportParser().parse(lines);
    230         assertTrue(bugreport.getCommandLine().isEmpty());
    231 
    232         lines = Arrays.asList("Command line: key=value");
    233         bugreport = new BugreportParser().parse(lines);
    234         assertEquals(1, bugreport.getCommandLine().size());
    235         assertEquals("value", bugreport.getCommandLine().get("key"));
    236 
    237         lines = Arrays.asList("Command line: key1=value1 key2=value2");
    238         bugreport = new BugreportParser().parse(lines);
    239         assertEquals(2, bugreport.getCommandLine().size());
    240         assertEquals("value1", bugreport.getCommandLine().get("key1"));
    241         assertEquals("value2", bugreport.getCommandLine().get("key2"));
    242 
    243         // Test a bad strings
    244         lines = Arrays.asList("Command line:   key1=value=withequals  key2=  ");
    245         bugreport = new BugreportParser().parse(lines);
    246         assertEquals(2, bugreport.getCommandLine().size());
    247         assertEquals("value=withequals", bugreport.getCommandLine().get("key1"));
    248         assertEquals("", bugreport.getCommandLine().get("key2"));
    249 
    250         lines = Arrays.asList("Command line: key1=value1 nonkey key2=");
    251         bugreport = new BugreportParser().parse(lines);
    252         assertEquals(3, bugreport.getCommandLine().size());
    253         assertEquals("value1", bugreport.getCommandLine().get("key1"));
    254         assertEquals("", bugreport.getCommandLine().get("key2"));
    255         assertNull(bugreport.getCommandLine().get("nonkey"));
    256     }
    257 
    258     /**
    259      * Test that a normal boot triggers a normal boot event and no unknown reason.
    260      */
    261     public void testParse_bootreason_kernel_good() {
    262         List<String> lines = Arrays.asList(
    263                 "========================================================",
    264                 "== dumpstate: 1999-01-01 02:03:04",
    265                 "========================================================",
    266                 "Command line: androidboot.bootreason=reboot",
    267                 "");
    268         BugreportItem bugreport = new BugreportParser().parse(lines);
    269         assertNotNull(bugreport.getLastKmsg());
    270         assertEquals(1, bugreport.getLastKmsg().getEvents().size());
    271         assertEquals("Last boot reason: reboot",
    272                 bugreport.getLastKmsg().getEvents().get(0).getStack());
    273         assertEquals("NORMAL_REBOOT", bugreport.getLastKmsg().getEvents().get(0).getCategory());
    274     }
    275 
    276     /**
    277      * Test that a kernel reset boot triggers a kernel reset event and no unknown reason.
    278      */
    279     public void testParse_bootreason_kernel_bad() {
    280         List<String> lines = Arrays.asList(
    281                 "========================================================",
    282                 "== dumpstate: 1999-01-01 02:03:04",
    283                 "========================================================",
    284                 "Command line: androidboot.bootreason=hw_reset",
    285                 "");
    286         BugreportItem bugreport = new BugreportParser().parse(lines);
    287         assertNotNull(bugreport.getLastKmsg());
    288         assertEquals(1, bugreport.getLastKmsg().getEvents().size());
    289         assertEquals("Last boot reason: hw_reset",
    290                 bugreport.getLastKmsg().getEvents().get(0).getStack());
    291         assertEquals("KERNEL_RESET", bugreport.getLastKmsg().getEvents().get(0).getCategory());
    292     }
    293 
    294     /**
    295      * Test that a normal boot triggers a normal boot event and no unknown reason.
    296      */
    297     public void testParse_bootreason_prop_good() {
    298         List<String> lines = Arrays.asList(
    299                 "========================================================",
    300                 "== dumpstate: 1999-01-01 02:03:04",
    301                 "========================================================",
    302                 "------ SYSTEM PROPERTIES ------",
    303                 "[ro.boot.bootreason]: [reboot]",
    304                 "");
    305         BugreportItem bugreport = new BugreportParser().parse(lines);
    306         assertNotNull(bugreport.getLastKmsg());
    307         assertEquals(1, bugreport.getLastKmsg().getEvents().size());
    308         assertEquals("Last boot reason: reboot",
    309                 bugreport.getLastKmsg().getEvents().get(0).getStack());
    310         assertEquals("NORMAL_REBOOT", bugreport.getLastKmsg().getEvents().get(0).getCategory());
    311     }
    312 
    313     /**
    314      * Test that a kernel reset boot triggers a kernel reset event and no unknown reason.
    315      */
    316     public void testParse_bootreason_prop_bad() {
    317         List<String> lines = Arrays.asList(
    318                 "========================================================",
    319                 "== dumpstate: 1999-01-01 02:03:04",
    320                 "========================================================",
    321                 "------ SYSTEM PROPERTIES ------",
    322                 "[ro.boot.bootreason]: [hw_reset]",
    323                 "");
    324         BugreportItem bugreport = new BugreportParser().parse(lines);
    325         assertNotNull(bugreport.getLastKmsg());
    326         assertEquals(1, bugreport.getLastKmsg().getEvents().size());
    327         assertEquals("Last boot reason: hw_reset",
    328                 bugreport.getLastKmsg().getEvents().get(0).getStack());
    329         assertEquals("KERNEL_RESET", bugreport.getLastKmsg().getEvents().get(0).getCategory());
    330         assertEquals("", bugreport.getLastKmsg().getEvents().get(0).getPreamble());
    331         assertEquals(0.0, bugreport.getLastKmsg().getEvents().get(0).getEventTime());
    332         assertEquals(0.0, bugreport.getLastKmsg().getStartTime());
    333         assertEquals(0.0, bugreport.getLastKmsg().getStopTime());
    334     }
    335 
    336     /**
    337      * Test that a kernel panic in the last kmsg and a kernel panic only triggers one kernel reset.
    338      */
    339     public void testParse_bootreason_duplicate() {
    340         List<String> lines = Arrays.asList(
    341                 "========================================================",
    342                 "== dumpstate: 1999-01-01 02:03:04",
    343                 "========================================================",
    344                 "Command line: androidboot.bootreason=hw_reset",
    345                 "------ SYSTEM PROPERTIES ------",
    346                 "[ro.boot.bootreason]: [hw_reset]",
    347                 "",
    348                 "------ LAST KMSG (/proc/last_kmsg) ------",
    349                 "[    0.000000] Initializing cgroup subsys cpu",
    350                 "[   16.203491] Kernel panic",
    351                 "");
    352         BugreportItem bugreport = new BugreportParser().parse(lines);
    353         assertNotNull(bugreport.getLastKmsg());
    354         assertEquals(1, bugreport.getLastKmsg().getEvents().size());
    355         assertEquals("Kernel panic", bugreport.getLastKmsg().getEvents().get(0).getStack());
    356         assertEquals("KERNEL_RESET", bugreport.getLastKmsg().getEvents().get(0).getCategory());
    357     }
    358 
    359     /**
    360      * Test that the trace is set correctly if there is only one ANR.
    361      */
    362     public void testSetAnrTrace_single() {
    363         List<String> lines = Arrays.asList(
    364                 "========================================================",
    365                 "== dumpstate: 2012-04-25 20:45:10",
    366                 "========================================================",
    367                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    368                 "04-25 17:17:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
    369                 "04-25 17:17:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
    370                 "04-25 17:17:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
    371                 "04-25 17:17:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
    372                 "",
    373                 "------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2012-04-25 17:17:08) ------",
    374                 "",
    375                 "----- pid 2887 at 2012-04-25 17:17:08 -----",
    376                 "Cmd line: com.android.package",
    377                 "",
    378                 "DALVIK THREADS:",
    379                 "(mutexes: tll=0 tsl=0 tscl=0 ghl=0)",
    380                 "",
    381                 "\"main\" prio=5 tid=1 SUSPENDED",
    382                 "  | group=\"main\" sCount=1 dsCount=0 obj=0x00000001 self=0x00000001",
    383                 "  | sysTid=2887 nice=0 sched=0/0 cgrp=foreground handle=0000000001",
    384                 "  | schedstat=( 0 0 0 ) utm=5954 stm=1017 core=0",
    385                 "  at class.method1(Class.java:1)",
    386                 "  at class.method2(Class.java:2)",
    387                 "  at class.method2(Class.java:2)",
    388                 "",
    389                 "----- end 2887 -----",
    390                 "");
    391 
    392         List<String> expectedStack = Arrays.asList(
    393                 "\"main\" prio=5 tid=1 SUSPENDED",
    394                 "  | group=\"main\" sCount=1 dsCount=0 obj=0x00000001 self=0x00000001",
    395                 "  | sysTid=2887 nice=0 sched=0/0 cgrp=foreground handle=0000000001",
    396                 "  | schedstat=( 0 0 0 ) utm=5954 stm=1017 core=0",
    397                 "  at class.method1(Class.java:1)",
    398                 "  at class.method2(Class.java:2)",
    399                 "  at class.method2(Class.java:2)");
    400 
    401         BugreportItem bugreport = new BugreportParser().parse(lines);
    402 
    403         assertNotNull(bugreport.getSystemLog());
    404         assertEquals(1, bugreport.getSystemLog().getAnrs().size());
    405         assertEquals(ArrayUtil.join("\n", expectedStack),
    406                 bugreport.getSystemLog().getAnrs().get(0).getTrace());
    407     }
    408 
    409     /**
    410      * Test that the trace is set correctly if there are multiple ANRs.
    411      */
    412     public void testSetAnrTrace_multiple() {
    413         List<String> lines = Arrays.asList(
    414                 "========================================================",
    415                 "== dumpstate: 2012-04-25 20:45:10",
    416                 "========================================================",
    417                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    418                 "04-25 17:17:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
    419                 "04-25 17:17:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
    420                 "04-25 17:17:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
    421                 "04-25 17:17:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
    422                 "04-25 17:18:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
    423                 "04-25 17:18:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
    424                 "04-25 17:18:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
    425                 "04-25 17:18:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
    426                 "04-25 17:19:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.different.pacakge",
    427                 "04-25 17:19:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
    428                 "04-25 17:19:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
    429                 "04-25 17:19:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
    430                 "",
    431                 "------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2012-04-25 17:18:08) ------",
    432                 "",
    433                 "----- pid 2887 at 2012-04-25 17:17:08 -----",
    434                 "Cmd line: com.android.package",
    435                 "",
    436                 "DALVIK THREADS:",
    437                 "(mutexes: tll=0 tsl=0 tscl=0 ghl=0)",
    438                 "",
    439                 "\"main\" prio=5 tid=1 SUSPENDED",
    440                 "  | group=\"main\" sCount=1 dsCount=0 obj=0x00000001 self=0x00000001",
    441                 "  | sysTid=2887 nice=0 sched=0/0 cgrp=foreground handle=0000000001",
    442                 "  | schedstat=( 0 0 0 ) utm=5954 stm=1017 core=0",
    443                 "  at class.method1(Class.java:1)",
    444                 "  at class.method2(Class.java:2)",
    445                 "  at class.method2(Class.java:2)",
    446                 "",
    447                 "----- end 2887 -----",
    448                 "");
    449 
    450         List<String> expectedStack = Arrays.asList(
    451                 "\"main\" prio=5 tid=1 SUSPENDED",
    452                 "  | group=\"main\" sCount=1 dsCount=0 obj=0x00000001 self=0x00000001",
    453                 "  | sysTid=2887 nice=0 sched=0/0 cgrp=foreground handle=0000000001",
    454                 "  | schedstat=( 0 0 0 ) utm=5954 stm=1017 core=0",
    455                 "  at class.method1(Class.java:1)",
    456                 "  at class.method2(Class.java:2)",
    457                 "  at class.method2(Class.java:2)");
    458 
    459         BugreportItem bugreport = new BugreportParser().parse(lines);
    460 
    461         assertNotNull(bugreport.getSystemLog());
    462         assertEquals(3, bugreport.getSystemLog().getAnrs().size());
    463         assertNull(bugreport.getSystemLog().getAnrs().get(0).getTrace());
    464         assertEquals(ArrayUtil.join("\n", expectedStack),
    465                 bugreport.getSystemLog().getAnrs().get(1).getTrace());
    466         assertNull(bugreport.getSystemLog().getAnrs().get(2).getTrace());
    467     }
    468 
    469     /**
    470      * Test that the trace is set correctly if there is not traces file.
    471      */
    472     public void testSetAnrTrace_no_traces() {
    473         List<String> lines = Arrays.asList(
    474                 "========================================================",
    475                 "== dumpstate: 2012-04-25 20:45:10",
    476                 "========================================================",
    477                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    478                 "04-25 17:17:08.445   312   366 E ActivityManager: ANR (application not responding) in process: com.android.package",
    479                 "04-25 17:17:08.445   312   366 E ActivityManager: Reason: keyDispatchingTimedOut",
    480                 "04-25 17:17:08.445   312   366 E ActivityManager: Load: 0.71 / 0.83 / 0.51",
    481                 "04-25 17:17:08.445   312   366 E ActivityManager: 33% TOTAL: 21% user + 11% kernel + 0.3% iowait",
    482                 "",
    483                 "*** NO ANR VM TRACES FILE (/data/anr/traces.txt): No such file or directory",
    484                 "");
    485 
    486         BugreportItem bugreport = new BugreportParser().parse(lines);
    487 
    488         assertNotNull(bugreport.getSystemLog());
    489         assertEquals(1, bugreport.getSystemLog().getAnrs().size());
    490         assertNull(bugreport.getSystemLog().getAnrs().get(0).getTrace());
    491     }
    492 
    493     /**
    494      * Add a test that ensures that the "new" style of stack dumping works. Traces aren't written to
    495      * a global trace file. Instead, each ANR event is written to a separate trace file (note the
    496      * "/data/anr/anr_4376042170248254515" instead of "/data/anr/traces.txt").
    497      */
    498     public void testAnrTraces_not_global_traceFile() {
    499         List<String> lines =
    500                 Arrays.asList(
    501                         "========================================================",
    502                         "== dumpstate: 2017-06-12 16:46:29",
    503                         "========================================================",
    504                         "------ SYSTEM LOG (logcat -v threadtime -v printable -v uid -d *:v) ------",
    505                         "--------- beginning of main  ",
    506                         "02-18 04:26:31.829  logd   468   468 W auditd  : type=2000 audit(0.0:1): initialized",
    507                         "02-18 04:26:33.783  logd   468   468 I auditd  : type=1403 audit(0.0:2): policy loaded auid=4294967295 ses=4294967295",
    508                         "02-18 04:26:33.783  logd   468   468 W auditd  : type=1404 audit(0.0:3): enforcing=1 old_enforcing=0 auid=4294967295 ses=4294967295",
    509                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager: ANR in com.example.android.helloactivity (com.example.android.helloactivity/.HelloActivity)",
    510                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager: PID: 7176",
    511                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager: Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)",
    512                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager: Load: 6.85 / 7.07 / 5.31",
    513                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager: CPU usage from 235647ms to 0ms ago (2017-06-12 16:41:49.415 to 2017-06-12 16:45:45.062):",
    514                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager:   7.7% 1848/com.ustwo.lwp: 4% user + 3.7% kernel / faults: 157 minor",
    515                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager:   7.7% 2536/com.google.android.googlequicksearchbox:search: 5.6% user + 2.1% kernel / faults: 195 minor",
    516                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager:   7.2% 1050/system_server: 4.5% user + 2.6% kernel / faults: 27117 minor ",
    517                         "06-12 16:45:47.426  1000  1050  1124 E ActivityManager:   5.3% 489/surfaceflinger: 2.9% user + 2.3% kernel / faults: 15 minor ",
    518                         "",
    519                         "------ VM TRACES AT LAST ANR (/data/anr/anr_4376042170248254515: 2017-06-12 16:45:47) ------",
    520                         "",
    521                         "----- pid 7176 at 2017-06-12 16:45:45 -----",
    522                         "Cmd line: com.example.android.helloactivity",
    523                         "",
    524                         "DALVIK THREADS:",
    525                         "(mutexes: tll=0 tsl=0 tscl=0 ghl=0)",
    526                         "",
    527                         "\"main\" daemon prio=5 tid=5 Waiting",
    528                         "  | group=\"system\" sCount=1 dsCount=0 flags=1 obj=0x140805e8 self=0x7caf4bf400",
    529                         "  | sysTid=7184 nice=4 cgrp=default sched=0/0 handle=0x7c9b4e44f0",
    530                         "  | state=S schedstat=( 507031 579062 19 ) utm=0 stm=0 core=3 HZ=100",
    531                         "  | stack=0x7c9b3e2000-0x7c9b3e4000 stackSize=1037KB",
    532                         "  | held mutexes=",
    533                         "  at java.lang.Object.wait(Native method)",
    534                         "  - waiting on <0x0281f7b7> (a java.lang.Class<java.lang.ref.ReferenceQueue>)",
    535                         "  at java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:178)",
    536                         "  - locked <0x0281f7b7> (a java.lang.Class<java.lang.ref.ReferenceQueue>)",
    537                         "  at java.lang.Daemons$Daemon.run(Daemons.java:103)",
    538                         "  at java.lang.Thread.run(Thread.java:764)",
    539                         "",
    540                         "----- end 7176 -----");
    541 
    542         // NOTE: The parser only extracts the main thread from the traces.
    543         List<String> expectedStack =
    544                 Arrays.asList(
    545                         "\"main\" daemon prio=5 tid=5 Waiting",
    546                         "  | group=\"system\" sCount=1 dsCount=0 flags=1 obj=0x140805e8 self=0x7caf4bf400",
    547                         "  | sysTid=7184 nice=4 cgrp=default sched=0/0 handle=0x7c9b4e44f0",
    548                         "  | state=S schedstat=( 507031 579062 19 ) utm=0 stm=0 core=3 HZ=100",
    549                         "  | stack=0x7c9b3e2000-0x7c9b3e4000 stackSize=1037KB",
    550                         "  | held mutexes=",
    551                         "  at java.lang.Object.wait(Native method)",
    552                         "  - waiting on <0x0281f7b7> (a java.lang.Class<java.lang.ref.ReferenceQueue>)",
    553                         "  at java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:178)",
    554                         "  - locked <0x0281f7b7> (a java.lang.Class<java.lang.ref.ReferenceQueue>)",
    555                         "  at java.lang.Daemons$Daemon.run(Daemons.java:103)",
    556                         "  at java.lang.Thread.run(Thread.java:764)");
    557 
    558         BugreportItem bugreport = new BugreportParser().parse(lines);
    559         assertNotNull(bugreport.getSystemLog());
    560         assertEquals(1, bugreport.getSystemLog().getAnrs().size());
    561         assertEquals(
    562                 ArrayUtil.join("\n", expectedStack),
    563                 bugreport.getSystemLog().getAnrs().get(0).getTrace());
    564     }
    565 
    566     /**
    567      * Test that missing sections in bugreport are set to {@code null}, not empty {@link IItem}s.
    568      */
    569     public void testNoSections() {
    570         List<String> lines = Arrays.asList(
    571                 "========================================================",
    572                 "== dumpstate: 2012-04-25 20:45:10",
    573                 "========================================================");
    574 
    575         BugreportItem bugreport = new BugreportParser().parse(lines);
    576         assertNotNull(bugreport);
    577         assertNull(bugreport.getDumpsys());
    578         assertNull(bugreport.getKernelLog());
    579         assertNull(bugreport.getMemInfo());
    580         assertNull(bugreport.getProcrank());
    581         assertNull(bugreport.getSystemLog());
    582         assertNull(bugreport.getSystemProps());
    583         assertNull(bugreport.getTop());
    584         assertNotNull(bugreport.getLastKmsg());
    585         List<MiscKernelLogItem> events = bugreport.getLastKmsg().getMiscEvents(
    586                 KernelLogParser.KERNEL_RESET);
    587         assertEquals(events.size(), 1);
    588         assertEquals(events.get(0).getStack(), "Unknown reason");
    589 
    590         lines = Arrays.asList(
    591                 "========================================================",
    592                 "== dumpstate: 2012-04-25 20:45:10",
    593                 "========================================================",
    594                 "",
    595                 "------ DUMPSYS (dumpsys) ------",
    596                 "",
    597                 "------ KERNEL LOG (dmesg) ------",
    598                 "",
    599                 "------ LAST KMSG (/proc/last_kmsg) ------",
    600                 "",
    601                 "------ MEMORY INFO (/proc/meminfo) ------",
    602                 "",
    603                 "------ PROCRANK (procrank) ------",
    604                 "",
    605                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    606                 "",
    607                 "------ SYSTEM PROPERTIES ------",
    608                 "",
    609                 "------ CPU INFO (top -n 1 -d 1 -m 30 -t) ------",
    610                 "");
    611 
    612         bugreport = new BugreportParser().parse(lines);
    613         assertNotNull(bugreport);
    614         assertNotNull(bugreport.getDumpsys());
    615         assertNull(bugreport.getKernelLog());
    616         assertNull(bugreport.getMemInfo());
    617         assertNull(bugreport.getProcrank());
    618         assertNull(bugreport.getSystemLog());
    619         assertNull(bugreport.getSystemProps());
    620         assertNull(bugreport.getTop());
    621         assertNotNull(bugreport.getLastKmsg());
    622         events = bugreport.getLastKmsg().getMiscEvents(KernelLogParser.KERNEL_RESET);
    623         assertEquals(events.size(), 1);
    624         assertEquals(events.get(0).getStack(), "Unknown reason");
    625     }
    626 
    627     /**
    628      * Test that section headers are correctly parsed.
    629      */
    630     public void testSectionHeader() {
    631         List<String> lines =
    632                 Arrays.asList(
    633                         "========================================================",
    634                         "== dumpstate: 2012-04-25 20:45:10",
    635                         "========================================================",
    636                         "------ DUMPSYS (dumpsys) ------",
    637                         "DUMP OF SERVICE SurfaceFlinger:",
    638                         "--DrmDisplayCompositor[0]: num_frames=1456 num_ms=475440 fps=3.06243",
    639                         "---- DrmDisplayCompositor Layers: num=3",
    640                         "------ DrmDisplayCompositor Layer: plane=17 crtc=20 crtc[x/y/w/h]=0/0/2560/1800",
    641                         "------ DrmDisplayCompositor Layer: plane=21 disabled",
    642                         "------ DrmDisplayCompositor Layer: plane=22 disabled",
    643                         "DUMP OF SERVICE batterystats:",
    644                         "Battery History (0% used, 1636 used of 256KB, 15 strings using 794):",
    645                         "    0 (15) RESET:TIME: 1970-01-10-06-23-28",
    646                         "          +45s702ms (2) 001 80080000 volt=4187",
    647                         "          +1m15s525ms (2) 001 80080000 temp=299 volt=4155",
    648                         "Statistics since last charged:",
    649                         "  Time on battery: 1h 5m 2s 4ms (9%) realtime, 1h 5m 2s 4ms (9%) uptime",
    650                         " Time on battery screen off: 1h 4m 5s 8ms (9%) realtime, 1h 4m 5s 8ms (9%) uptime",
    651                         " All kernel wake locks:",
    652                         " Kernel Wake lock PowerManagerService.WakeLocks: 5m 10s 6ms (2 times) realtime",
    653                         " Kernel Wake lock msm_serial_hs_rx: 2m 13s 612ms (258 times) realtime",
    654                         "",
    655                         "  All partial wake locks:",
    656                         "  Wake lock 1001 ProxyController: 1h 4m 47s 565ms (4 times) realtime",
    657                         "  Wake lock 1013 AudioMix: 1s 979ms (3 times) realtime",
    658                         "",
    659                         "  All wakeup reasons:",
    660                         "  Wakeup reason 2:bcmsdh_sdmmc:2:qcom,smd:2:msmgio: 1m 5s 4ms (2 times) realtime",
    661                         "  Wakeup reason 2:qcom,smd-rpm:2:fc4c.qcom,spmi: 7m 1s 914ms (7 times) realtime",
    662                         "DUMP OF SERVICE package:",
    663                         "Package [com.google.android.calculator] (e075c9d):",
    664                         "  use rId=10071",
    665                         "  secondaryCpuAbi=null",
    666                         "  versionCode=73000302 minSdk=10000 targetSdk=10000",
    667                         "  versionName=7.3 (3821978)",
    668                         "  splits=[base]",
    669                         "DUMP OF SERVICE procstats:",
    670                         "COMMITTED STATS FROM 2015-09-30-07-44-54:",
    671                         "  * system / 1000 / v23:",
    672                         "           TOTAL: 100% (118MB-118MB-118MB/71MB-71MB-71MB over 1)",
    673                         "      Persistent: 100% (118MB-118MB-118MB/71MB-71MB-71MB over 1)",
    674                         " * com.android.phone / 1001 / v23:",
    675                         "           TOTAL: 6.7%",
    676                         "      Persistent: 6.7%",
    677                         "");
    678         BugreportItem bugreport = new BugreportParser().parse(lines);
    679         assertNotNull(bugreport.getDumpsys());
    680         assertNotNull(bugreport.getDumpsys().getBatteryStats());
    681         assertNotNull(bugreport.getDumpsys().getPackageStats());
    682         assertNotNull(bugreport.getDumpsys().getProcStats());
    683     }
    684 
    685     /**
    686      * Test that an empty input returns {@code null}.
    687      */
    688     public void testEmptyInput() {
    689         BugreportItem item = new BugreportParser().parse(Arrays.asList(""));
    690         assertNull(item);
    691     }
    692 
    693     /**
    694      * Test that app names from logcat events are populated by matching the logcat PIDs with the
    695      * PIDs from the logcat.
    696      */
    697     public void testSetAppsFromProcrank() {
    698         List<String> lines = Arrays.asList(
    699                 "========================================================",
    700                 "== dumpstate: 2012-04-25 20:45:10",
    701                 "========================================================",
    702                 "------ PROCRANK (procrank) ------",
    703                 "  PID      Vss      Rss      Pss      Uss  cmdline",
    704                 " 3064   87136K   81684K   52829K   50012K  com.android.package1",
    705                 " 3066   87136K   81684K   52829K   50012K  com.android.package2",
    706                 "                          ------   ------  ------",
    707                 "                          203624K  163604K  TOTAL",
    708                 "RAM: 731448K total, 415804K free, 9016K buffers, 108548K cached",
    709                 "[procrank: 1.6s elapsed]",
    710                 "------ SYSTEM LOG (logcat -v threadtime -d *:v) ------",
    711                 "04-25 09:55:47.799  3064  3082 E AndroidRuntime: java.lang.Exception",
    712                 "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method1(Class.java:1)",
    713                 "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method2(Class.java:2)",
    714                 "04-25 09:55:47.799  3064  3082 E AndroidRuntime: \tat class.method3(Class.java:3)",
    715                 "04-25 09:55:47.799  3065  3083 E AndroidRuntime: java.lang.Exception",
    716                 "04-25 09:55:47.799  3065  3083 E AndroidRuntime: \tat class.method1(Class.java:1)",
    717                 "04-25 09:55:47.799  3065  3083 E AndroidRuntime: \tat class.method2(Class.java:2)",
    718                 "04-25 09:55:47.799  3065  3083 E AndroidRuntime: \tat class.method3(Class.java:3)",
    719                 "04-25 09:55:47.799  3065  3084 E AndroidRuntime: FATAL EXCEPTION: main",
    720                 "04-25 09:55:47.799  3066  3084 E AndroidRuntime: Process: com.android.package3, PID: 1234",
    721                 "04-25 09:55:47.799  3066  3084 E AndroidRuntime: java.lang.Exception",
    722                 "04-25 09:55:47.799  3066  3084 E AndroidRuntime: \tat class.method1(Class.java:1)",
    723                 "04-25 09:55:47.799  3066  3084 E AndroidRuntime: \tat class.method2(Class.java:2)",
    724                 "04-25 09:55:47.799  3066  3084 E AndroidRuntime: \tat class.method3(Class.java:3)");
    725 
    726         BugreportItem bugreport = new BugreportParser().parse(lines);
    727         assertNotNull(bugreport.getSystemLog());
    728         assertEquals(3, bugreport.getSystemLog().getJavaCrashes().size());
    729         assertEquals("com.android.package1",
    730                 bugreport.getSystemLog().getJavaCrashes().get(0).getApp());
    731         assertNull(bugreport.getSystemLog().getJavaCrashes().get(1).getApp());
    732         assertEquals("com.android.package3",
    733                 bugreport.getSystemLog().getJavaCrashes().get(2).getApp());
    734     }
    735 
    736     /**
    737      * Some Android devices refer to SYSTEM LOG as MAIN LOG. Check that parser recognizes this
    738      * alternate syntax.
    739      */
    740     public void testSystemLogAsMainLog() {
    741         List<String> lines = Arrays.asList(
    742                 "------ MAIN LOG (logcat -b main -b system -v threadtime -d *:v) ------",
    743                 "--------- beginning of /dev/log/system",
    744                 "12-11 19:48:07.945  1484  1508 D BatteryService: update start");
    745         BugreportItem bugreport = new BugreportParser().parse(lines);
    746         assertNotNull(bugreport.getSystemLog());
    747     }
    748 
    749     /**
    750      * Some Android devices refer to SYSTEM LOG as MAIN AND SYSTEM LOG. Check that parser
    751      * recognizes this alternate syntax.
    752      */
    753     public void testSystemAndMainLog() {
    754         List<String> lines = Arrays.asList(
    755                 "------ MAIN AND SYSTEM LOG (logcat -b main -b system -v threadtime -d *:v) ------",
    756                 "--------- beginning of /dev/log/system",
    757                 "12-17 15:15:12.877  1994  2019 D UiModeManager: updateConfigurationLocked: ");
    758         BugreportItem bugreport = new BugreportParser().parse(lines);
    759         assertNotNull(bugreport.getSystemLog());
    760     }
    761 
    762     private Date parseTime(String timeStr) throws ParseException {
    763         DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    764         return formatter.parse(timeStr);
    765     }
    766 }
    767