summaryrefslogtreecommitdiff
path: root/javatests/src/com/android/loganalysis/parser/DmesgParserTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'javatests/src/com/android/loganalysis/parser/DmesgParserTest.java')
-rw-r--r--javatests/src/com/android/loganalysis/parser/DmesgParserTest.java317
1 files changed, 317 insertions, 0 deletions
diff --git a/javatests/src/com/android/loganalysis/parser/DmesgParserTest.java b/javatests/src/com/android/loganalysis/parser/DmesgParserTest.java
new file mode 100644
index 0000000..e4ea7af
--- /dev/null
+++ b/javatests/src/com/android/loganalysis/parser/DmesgParserTest.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.loganalysis.parser;
+
+import com.android.loganalysis.item.DmesgActionInfoItem;
+import com.android.loganalysis.item.DmesgItem;
+import com.android.loganalysis.item.DmesgServiceInfoItem;
+import com.android.loganalysis.item.DmesgStageInfoItem;
+import com.android.loganalysis.item.DmesgModuleInfoItem;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link DmesgParser}.
+ */
+public class DmesgParserTest extends TestCase {
+
+ private static final String BOOT_ANIMATION = "bootanim";
+ private static final String NETD = "netd";
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String TOTAL_MODULE = "TOTAL_MODULE";
+ private static final String[] LINES =
+ new String[] {
+ "[ 0.370107] init: Loading module /lib/modules/foo.ko with args ''",
+ "[ 0.372497] init: Loaded kernel module /lib/modules/foo.ko",
+ "[ 0.372500] init: Loading module /lib/modules/bar.ko with args ''",
+ "[ 1.115467] init: Loaded 198 kernel modules took 748 ms",
+ "[ 2.471163] init: Wait for property 'apexd.status=ready' took 403ms",
+ "[ 3.786943] ueventd: Coldboot took 0.701291 seconds",
+ "[ 22.962730] init: starting service 'bootanim'...",
+ "[ 23.252321] init: starting service 'netd'...",
+ "[ 29.331069] ipa-wan ipa_wwan_ioctl:1428 dev(rmnet_data0) register to IPA",
+ "[ 32.182592] ueventd: fixup /sys/devices/virtual/input/poll_delay 0 1004 660",
+ "[ 35.642666] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts",
+ "[ 39.855818] init: Service 'bootanim' (pid 588) exited with status 0",
+ "[ 41.665818] init: init first stage started!",
+ "[ 44.942872] init: processing action (early-init) from (/init.rc:13)",
+ "[ 47.233446] init: processing action (set_mmap_rnd_bits) from (<Builtin "
+ + "Action>:0)",
+ "[ 47.240083] init: processing action (set_kptr_restrict) from (<Builtin"
+ + " Action>:0)",
+ "[ 47.245778] init: processing action (keychord_init) from (<Builtin Action>:0)",
+ "[ 52.361049] init: processing action (persist.sys.usb.config=* boot) from"
+ + " (<Builtin Action>:0)",
+ "[ 52.361108] init: processing action (enable_property_trigger) from (<Builtin"
+ + " Action>:0)",
+ "[ 52.361313] init: processing action (security.perf_harden=1) from"
+ + " (/init.rc:677)",
+ "[ 52.361495] init: processing action (ro.debuggable=1) from (/init.rc:700)",
+ "[ 58.298293] init: processing action (sys.boot_completed=1)",
+ "[ 59.331069] ipa-wan ipa_wwan_ioctl:1428 dev(rmnet_data0) register to IPA",
+ "[ 62.182592] ueventd: fixup /sys/devices/virtual/input/poll_delay 0 1004 660",
+ "[ 65.642666] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts",
+ "[ 69.855818] init: Service 'bootanim' (pid 588) exited with status 0"
+ };
+
+ private static final Map<String, DmesgServiceInfoItem> EXPECTED_SERVICE_INFO_ITEMS =
+ getExpectedServiceInfoItems();
+
+ private static final List<DmesgStageInfoItem> EXPECTED_STAGE_INFO_ITEMS =
+ getExpectedStageInfoItems();
+
+ private static final List<DmesgActionInfoItem> EXPECTED_ACTION_INFO_ITEMS =
+ getExpectedActionInfoItems();
+
+ private static final Map<String, DmesgModuleInfoItem> EXPECTED_MODULE_INFO_ITEMS =
+ getExpectedModuleInfoItems();
+
+ /**
+ * Test for empty dmesg logs passed to the DmesgParser
+ */
+ public void testEmptyDmesgLog() throws IOException {
+ String[] lines = new String[] {""};
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(String.join("\n", lines).getBytes())))) {
+ DmesgParser dmesgParser = new DmesgParser();
+ dmesgParser.parseInfo(bufferedReader);
+ assertEquals("Service info items list should be empty", 0,
+ dmesgParser.getServiceInfoItems().size());
+ }
+ }
+
+ /**
+ * Test for complete dmesg logs passed as list of strings
+ */
+ public void testCompleteDmesgLog_passedAsList() {
+
+ DmesgParser dmesgParser = new DmesgParser();
+ DmesgItem actualDmesgItem = dmesgParser.parse(Arrays.asList(LINES));
+
+ assertEquals("Service info items list size should be 2", 2,
+ dmesgParser.getServiceInfoItems().size());
+ assertEquals("Stage info items list size should be 3",3,
+ dmesgParser.getStageInfoItems().size());
+ assertEquals("Action info items list size should be 9",9,
+ dmesgParser.getActionInfoItems().size());
+ assertEquals(
+ "Module info items list size should be 3",
+ 3,
+ dmesgParser.getModuleInfoItems().size());
+
+ assertEquals(EXPECTED_SERVICE_INFO_ITEMS, actualDmesgItem.getServiceInfoItems());
+ assertEquals(EXPECTED_STAGE_INFO_ITEMS, actualDmesgItem.getStageInfoItems());
+ assertEquals(EXPECTED_ACTION_INFO_ITEMS, actualDmesgItem.getActionInfoItems());
+ assertEquals(EXPECTED_MODULE_INFO_ITEMS, actualDmesgItem.getModuleInfoItems());
+ }
+
+ /**
+ * Test for complete dmesg logs passed as buffered input
+ */
+ public void testCompleteDmesgLog_passedAsBufferedInput() throws IOException {
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(String.join("\n", LINES).getBytes())))) {
+ DmesgParser dmesgParser = new DmesgParser();
+ dmesgParser.parseInfo(bufferedReader);
+ assertEquals("Service info items list size should be 2", 2,
+ dmesgParser.getServiceInfoItems().size());
+ assertEquals("Stage info items list size should be 3", 3,
+ dmesgParser.getStageInfoItems().size());
+ assertEquals("Action info items list size should be 9",9,
+ dmesgParser.getActionInfoItems().size());
+ assertEquals(
+ "Module info items list size should be 3",
+ 3,
+ dmesgParser.getModuleInfoItems().size());
+ }
+ }
+
+ /**
+ * Test service which logs both the start and end time
+ */
+ public void testCompleteServiceInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseServiceInfo(line);
+ }
+
+ assertEquals("There should be two service infos", 2,
+ dmesgParser.getServiceInfoItems().size());
+ assertEquals(EXPECTED_SERVICE_INFO_ITEMS, dmesgParser.getServiceInfoItems());
+ }
+
+ /**
+ * Test service which logs only the start time
+ */
+ public void testStartServiceInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseServiceInfo(line);
+ }
+ List<DmesgServiceInfoItem> serviceInfoItems = new ArrayList<>(
+ dmesgParser.getServiceInfoItems().values());
+ assertEquals("There should be exactly two service infos", 2, serviceInfoItems.size());
+ assertEquals("Service name is not bootanim", BOOT_ANIMATION,
+ serviceInfoItems.get(0).getServiceName());
+ assertEquals("Service name is not netd", NETD, serviceInfoItems.get(1).getServiceName());
+ }
+
+ /**
+ * Test multiple service info parsed correctly and stored in the same order logged in
+ * the file.
+ */
+ public void testMultipleServiceInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseServiceInfo(line);
+ }
+ assertEquals("There should be exactly two service info", 2,
+ dmesgParser.getServiceInfoItems().size());
+ assertEquals(EXPECTED_SERVICE_INFO_ITEMS, dmesgParser.getServiceInfoItems());
+ }
+
+ /**
+ * Test invalid patterns on the start and exit service logs
+ */
+ public void testInvalidServiceLogs() {
+ // Added space at the end of the start and exit of service logs to make it invalid
+ String[] lines = new String[] {
+ "[ 22.962730] init: starting service 'bootanim'... ",
+ "[ 23.252321] init: starting service 'netd'... ",
+ "[ 29.331069] ipa-wan ipa_wwan_ioctl:1428 dev(rmnet_data0) register to IPA",
+ "[ 32.182592] ueventd: fixup /sys/devices/virtual/input/poll_delay 0 1004 660",
+ "[ 35.642666] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts",
+ "[ 39.855818] init: Service 'bootanim' (pid 588) exited with status 0 "};
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : lines) {
+ dmesgParser.parseServiceInfo(line);
+ }
+ List<DmesgServiceInfoItem> serviceInfoItems = new ArrayList<>(
+ dmesgParser.getServiceInfoItems().values());
+ assertEquals("No service info should be available", 0, serviceInfoItems.size());
+ }
+
+ /**
+ * Test init stages' start time logs
+ */
+ public void testCompleteStageInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseStageInfo(line);
+ }
+ List<DmesgStageInfoItem> stageInfoItems = dmesgParser.getStageInfoItems();
+ assertEquals(3, stageInfoItems.size());
+ assertEquals(EXPECTED_STAGE_INFO_ITEMS, stageInfoItems);
+ }
+
+ /** Test processing action start time logs */
+ public void testCompleteActionInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseActionInfo(line);
+ }
+ List<DmesgActionInfoItem> actualActionInfoItems = dmesgParser.getActionInfoItems();
+ assertEquals(9, actualActionInfoItems.size());
+ assertEquals(EXPECTED_ACTION_INFO_ITEMS, actualActionInfoItems);
+ }
+
+ /** Test incomplete module loaded pattern */
+ public void testIncompleteModuleInfo() {
+ DmesgParser dmesgParser = new DmesgParser();
+ for (String line : LINES) {
+ dmesgParser.parseModuleInfo(line);
+ }
+ List<DmesgModuleInfoItem> actualModuleInfoItems =
+ new ArrayList<>(dmesgParser.getModuleInfoItems().values());
+ assertEquals(EXPECTED_MODULE_INFO_ITEMS, dmesgParser.getModuleInfoItems());
+ assertEquals(3, actualModuleInfoItems.size());
+ assertEquals(
+ "Duration should be -1L",
+ Long.valueOf(-1L),
+ actualModuleInfoItems.get(0).getModuleDuration());
+ }
+
+ private static List<DmesgActionInfoItem> getExpectedActionInfoItems() {
+ return Arrays.asList(
+ new DmesgActionInfoItem("/init.rc:13", "early-init", 44942L),
+ new DmesgActionInfoItem("<Builtin Action>:0", "set_mmap_rnd_bits", 47233L),
+ new DmesgActionInfoItem("<Builtin Action>:0", "set_kptr_restrict", 47240L),
+ new DmesgActionInfoItem("<Builtin Action>:0", "keychord_init", 47245L),
+ new DmesgActionInfoItem(
+ "<Builtin Action>:0", "persist.sys.usb.config=* boot", 52361L),
+ new DmesgActionInfoItem("<Builtin Action>:0", "enable_property_trigger", 52361L),
+ new DmesgActionInfoItem("/init.rc:677", "security.perf_harden=1", 52361L),
+ new DmesgActionInfoItem("/init.rc:700", "ro.debuggable=1", 52361L),
+ new DmesgActionInfoItem(null, "sys.boot_completed=1", 58298L));
+ }
+
+ private static List<DmesgStageInfoItem> getExpectedStageInfoItems() {
+ return Arrays.asList(
+ new DmesgStageInfoItem("init_Wait for property 'apexd.status=ready'", null, 403L),
+ new DmesgStageInfoItem("ueventd_Coldboot", null, 701L),
+ new DmesgStageInfoItem("first", 41665L, null));
+ }
+
+ private static Map<String, DmesgServiceInfoItem> getExpectedServiceInfoItems() {
+ Map<String, DmesgServiceInfoItem> serviceInfoItemsMap = new HashMap<>();
+ DmesgServiceInfoItem bootanimServiceInfoItem = new DmesgServiceInfoItem();
+ bootanimServiceInfoItem.setServiceName(BOOT_ANIMATION);
+ bootanimServiceInfoItem.setStartTime(22962L);
+ bootanimServiceInfoItem.setEndTime(69855L);
+
+ DmesgServiceInfoItem netdServiceInfoItem = new DmesgServiceInfoItem();
+ netdServiceInfoItem.setServiceName(NETD);
+ netdServiceInfoItem.setStartTime(23252L);
+
+ serviceInfoItemsMap.put(BOOT_ANIMATION, bootanimServiceInfoItem);
+ serviceInfoItemsMap.put(NETD, netdServiceInfoItem);
+
+ return serviceInfoItemsMap;
+ }
+
+ private static Map<String, DmesgModuleInfoItem> getExpectedModuleInfoItems() {
+ Map<String, DmesgModuleInfoItem> moduleInfoItemsMap = new HashMap<>();
+ DmesgModuleInfoItem fooModuleInfo = new DmesgModuleInfoItem();
+ fooModuleInfo.setModuleName(FOO);
+ fooModuleInfo.setStartTime(370L);
+ fooModuleInfo.setEndTime(372L);
+
+ DmesgModuleInfoItem barModuleInfo = new DmesgModuleInfoItem();
+ barModuleInfo.setModuleName(BAR);
+ barModuleInfo.setStartTime(372L);
+
+ DmesgModuleInfoItem totalInfoItem = new DmesgModuleInfoItem();
+ totalInfoItem.setModuleName(TOTAL_MODULE);
+ totalInfoItem.setModuleCount("198");
+ totalInfoItem.setModuleDuration(748L);
+
+ moduleInfoItemsMap.put(FOO, fooModuleInfo);
+ moduleInfoItemsMap.put(BAR, barModuleInfo);
+ moduleInfoItemsMap.put(TOTAL_MODULE, totalInfoItem);
+
+ return moduleInfoItemsMap;
+ }
+}