Add Atrace test for trace content
bug:21559370
Change-Id: Ie1d7dfa58c88da3b1c8d5663f9852f12590539b0
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 4035af7..c389833 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -67,6 +67,7 @@
cts_support_packages := \
CtsAccelerationTestStubs \
CtsAppTestStubs \
+ CtsAtraceTestApp \
CtsCertInstallerApp \
CtsDeviceAdmin \
CtsDeviceOpenGl \
diff --git a/hostsidetests/atrace/AtraceTestApp/Android.mk b/hostsidetests/atrace/AtraceTestApp/Android.mk
new file mode 100644
index 0000000..0eb7cfd
--- /dev/null
+++ b/hostsidetests/atrace/AtraceTestApp/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2009 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_PACKAGE_NAME := CtsAtraceTestApp
+
+# sign this app with a different cert than CtsSimpleAppInstallDiffCert
+#LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+
+#LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/atrace/AtraceTestApp/AndroidManifest.xml b/hostsidetests/atrace/AtraceTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..a86f7f0
--- /dev/null
+++ b/hostsidetests/atrace/AtraceTestApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.atracetestapp">
+ <!--
+ A simple app with a tracing section to test that apps tracing signals are
+ emitted by atrace.
+ -->
+ <application>
+ <activity android:name=".AtraceTestAppActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/atrace/AtraceTestApp/src/com/android/cts/atracetestapp/AtraceTestAppActivity.java b/hostsidetests/atrace/AtraceTestApp/src/com/android/cts/atracetestapp/AtraceTestAppActivity.java
new file mode 100644
index 0000000..0269d0d
--- /dev/null
+++ b/hostsidetests/atrace/AtraceTestApp/src/com/android/cts/atracetestapp/AtraceTestAppActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 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.cts.atracetestapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Trace;
+
+public class AtraceTestAppActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Trace.beginSection("traceable-app-test-section");
+ super.onCreate(savedInstanceState);
+ Trace.endSection();
+ }
+}
diff --git a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
index f7af31c..ee0511d 100644
--- a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
+++ b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
@@ -16,27 +16,40 @@
package android.atrace.cts;
+import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Test to check that atrace is usable, to enable usage of systrace.
*/
-public class AtraceHostTest extends DeviceTestCase {
+public class AtraceHostTest extends DeviceTestCase implements IBuildReceiver {
private static final String TAG = "AtraceHostTest";
- private ITestDevice mDevice;
+ private static final String TEST_APK = "CtsAtraceTestApp.apk";
+ private static final String TEST_PKG = "com.android.cts.atracetestapp";
+ private CtsBuildHelper mCtsBuild;
+
+ /**
+ * {@inheritDoc}
+ */
@Override
- protected void setUp() throws Exception {
- super.setUp();
- mDevice = getDevice();
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
}
// Collection of all userspace tags, and 'sched'
@@ -65,7 +78,7 @@
* Tests that atrace exists and is runnable with no args
*/
public void testSimpleRun() throws Exception {
- String output = mDevice.executeShellCommand("atrace");
+ String output = getDevice().executeShellCommand("atrace");
String[] lines = output.split("\\r?\\n");
// check for expected stdout
@@ -80,7 +93,7 @@
* Tests the output of "atrace --list_categories" to ensure required categories exist.
*/
public void testCategories() throws Exception {
- String output = mDevice.executeShellCommand("atrace --list_categories");
+ String output = getDevice().executeShellCommand("atrace --list_categories");
String[] categories = output.split("\\r?\\n");
Set<String> requiredCategories = new HashSet<String>(sRequiredCategoriesList);
@@ -101,4 +114,120 @@
fail("Expected categories missing from atrace");
}
}
+
+
+ private static final String TRACE_MARKER_REGEX =
+ "\\s*(\\S+)-(\\d+)\\s+\\(\\s*(\\d+)\\).*tracing_mark_write:\\s*(B|E)(.*)";
+ /**
+ * Tests that atrace captures app launch, including app level tracing
+ */
+ public void testTracingContent() throws Exception {
+ String atraceOutput = null;
+ try {
+ // cleanup test apps that might be installed from previous partial test run
+ getDevice().uninstallPackage(TEST_PKG);
+
+ // install the test app
+ File testAppFile = mCtsBuild.getTestApp(TEST_APK);
+ String installResult = getDevice().installPackage(testAppFile, false);
+ assertNull(
+ String.format("failed to install simple app. Reason: %s", installResult),
+ installResult);
+
+ // capture a launch of the app with async tracing
+ String atraceArgs = "-a " + TEST_PKG + " -c -b 16000 view"; // TODO: zipping
+ getDevice().executeShellCommand("atrace --async_stop " + atraceArgs);
+ getDevice().executeShellCommand("atrace --async_start " + atraceArgs);
+ String start = getDevice().executeShellCommand("am start " + TEST_PKG);
+ getDevice().executeShellCommand("sleep 1");
+ atraceOutput = getDevice().executeShellCommand("atrace --async_dump " + atraceArgs);
+ } finally {
+ getDevice().uninstallPackage(TEST_PKG);
+ }
+ assertNotNull(atraceOutput);
+
+
+ // now parse the trace data (see external/chromium-trace/systrace.py)
+ final String MARKER = "TRACE:";
+ int dataStart = atraceOutput.indexOf(MARKER);
+ assertTrue(dataStart >= 0);
+ String traceData = atraceOutput.substring(dataStart + MARKER.length());
+
+ /**
+ * Pattern that matches standard begin/end userspace tracing.
+ *
+ * Groups are:
+ * 1 - truncated thread name
+ * 2 - tid
+ * 3 - pid
+ * 4 - B/E
+ * 5 - ignored, for grouping
+ * 6 - if B, section title, else null
+ */
+ final Pattern beginEndPattern = Pattern.compile(
+ "\\s*(\\S+)-(\\d+)\\s+\\(\\s*(\\d+)\\).*tracing_mark_write:\\s*(B|E)(\\|\\d+\\|(.+))?");
+
+ int appPid = -1;
+ String line;
+
+ // list of tags expected to be seen on app launch, in order.
+ String[] requiredSectionList = {
+ "traceable-app-test-section",
+ "inflate",
+ "performTraversals",
+ "measure",
+ "layout",
+ "draw",
+ "Record View#draw()"
+ };
+ int nextSectionIndex = 0;
+ int matches = 0;
+ try (BufferedReader reader = new BufferedReader(new StringReader(traceData))) {
+ while ((line = reader.readLine()) != null) {
+ Matcher matcher = beginEndPattern.matcher(line);
+ if (matcher.find()) {
+ matches++;
+
+ String truncatedThreadName = matcher.group(1);
+ assertNotNull(truncatedThreadName);
+
+ int tid = assertInt(matcher.group(2));
+ assertTrue(tid > 0);
+ int pid = assertInt(matcher.group(3));
+ assertTrue(pid > 0);
+
+ if (TEST_PKG.endsWith(truncatedThreadName)) {
+ // should be something like "s.aptracetestapp" since beginning may be truncated
+ if (appPid == -1) {
+ appPid = pid;
+ } else {
+ assertEquals(appPid, pid);
+ }
+
+ if ("B".equals(matcher.group(4))) {
+ String sectionTitle = matcher.group(6);
+ if (nextSectionIndex < requiredSectionList.length
+ && requiredSectionList[nextSectionIndex].equals(sectionTitle)) {
+ nextSectionIndex++;
+ }
+ }
+ }
+ }
+ }
+ }
+ assertTrue("Unable to parse any userspace sections from atrace output",
+ matches != 0);
+ assertEquals("Didn't see required list of traced sections, in order",
+ requiredSectionList.length, nextSectionIndex);
+ }
+
+ private static int assertInt(String input) {
+ try {
+ return Integer.parseInt(input);
+ } catch (NumberFormatException e) {
+ fail("Expected an integer but found \"" + input + "\"");
+ // Won't be hit, above throws AssertException
+ return -1;
+ }
+ }
}