summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/tools/localtools/Android.bp29
-rw-r--r--cmds/statsd/tools/localtools/TEST_MAPPING8
-rw-r--r--cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java52
-rw-r--r--cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java13
-rw-r--r--cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java335
-rw-r--r--cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java326
-rw-r--r--cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java169
7 files changed, 789 insertions, 143 deletions
diff --git a/cmds/statsd/tools/localtools/Android.bp b/cmds/statsd/tools/localtools/Android.bp
index 75a57a3f3068..69a43a8f4712 100644
--- a/cmds/statsd/tools/localtools/Android.bp
+++ b/cmds/statsd/tools/localtools/Android.bp
@@ -11,9 +11,8 @@ java_binary_host {
],
}
-java_binary_host {
- name: "statsd_testdrive",
- manifest: "testdrive_manifest.txt",
+java_library_host {
+ name: "statsd_testdrive_lib",
srcs: [
"src/com/android/statsd/shelltools/testdrive/*.java",
"src/com/android/statsd/shelltools/Utils.java",
@@ -22,4 +21,26 @@ java_binary_host {
"platformprotos",
"guava",
],
-} \ No newline at end of file
+}
+
+
+java_binary_host {
+ name: "statsd_testdrive",
+ manifest: "testdrive_manifest.txt",
+ static_libs: [
+ "statsd_testdrive_lib",
+ ],
+}
+
+java_test_host {
+ name: "statsd_testdrive_test",
+ test_suites: ["general-tests"],
+ srcs: ["test/com/android/statsd/shelltools/testdrive/*.java"],
+ static_libs: [
+ "statsd_testdrive_lib",
+ "junit",
+ "platformprotos",
+ "guava",
+ ],
+}
+
diff --git a/cmds/statsd/tools/localtools/TEST_MAPPING b/cmds/statsd/tools/localtools/TEST_MAPPING
new file mode 100644
index 000000000000..7c8a3db5c610
--- /dev/null
+++ b/cmds/statsd/tools/localtools/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "statsd_testdrive_test",
+ "host": true
+ }
+ ]
+}
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
index 2909048da7ea..6a74480b505e 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
@@ -229,4 +229,56 @@ public class Utils {
}
return null;
}
+
+ /**
+ * Returns ANDROID_SERIAL environment variable, or null if that is undefined or unavailable.
+ * @param logger Destination of error messages.
+ * @return String value of ANDROID_SERIAL environment variable, or null.
+ */
+ public static String getDefaultDevice(Logger logger) {
+ try {
+ return System.getenv("ANDROID_SERIAL");
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Failed to check ANDROID_SERIAL environment variable.",
+ ex);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the device to use if one can be deduced, or null.
+ * @param device Command-line specified device, or null.
+ * @param connectedDevices List of all connected devices.
+ * @param defaultDevice Environment-variable specified device, or null.
+ * @param logger Destination of error messages.
+ * @return Device to use, or null.
+ */
+ public static String chooseDevice(String device, List<String> connectedDevices,
+ String defaultDevice, Logger logger) {
+ if (connectedDevices == null || connectedDevices.isEmpty()) {
+ logger.severe("No connected device.");
+ return null;
+ }
+ if (device != null) {
+ if (connectedDevices.contains(device)) {
+ return device;
+ }
+ logger.severe("Device not connected: " + device);
+ return null;
+ }
+ if (connectedDevices.size() == 1) {
+ return connectedDevices.get(0);
+ }
+ if (defaultDevice != null) {
+ if (connectedDevices.contains(defaultDevice)) {
+ return defaultDevice;
+ } else {
+ logger.severe("ANDROID_SERIAL device is not connected: " + defaultDevice);
+ return null;
+ }
+ }
+ logger.severe("More than one device is connected. Choose one"
+ + " with -s DEVICE_SERIAL or environment variable ANDROID_SERIAL.");
+ return null;
+ }
}
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
index 7db514180b9a..ec3c7df7bfba 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
@@ -27,7 +27,6 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
-import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -112,17 +111,9 @@ public class LocalDrive {
}
List<String> connectedDevices = Utils.getDeviceSerials(sLogger);
- if (connectedDevices == null || connectedDevices.size() == 0) {
- sLogger.log(Level.SEVERE, "No device connected.");
- return;
- }
- if (connectedDevices.size() == 1 && deviceSerial == null) {
- deviceSerial = connectedDevices.get(0);
- }
-
+ deviceSerial = Utils.chooseDevice(deviceSerial, connectedDevices,
+ Utils.getDefaultDevice(sLogger), sLogger);
if (deviceSerial == null) {
- sLogger.log(Level.SEVERE, "More than one devices connected. Please specify"
- + " with -s DEVICE_SERIAL");
return;
}
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index 54a744b654cb..8ac251e39a18 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -15,6 +15,7 @@
*/
package com.android.statsd.shelltools.testdrive;
+import com.android.internal.os.StatsdConfigProto;
import com.android.internal.os.StatsdConfigProto.AtomMatcher;
import com.android.internal.os.StatsdConfigProto.EventMetric;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
@@ -29,6 +30,7 @@ import com.android.os.StatsLog.ConfigMetricsReportList;
import com.android.os.StatsLog.StatsLogReport;
import com.android.statsd.shelltools.Utils;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.Files;
import java.io.File;
@@ -39,6 +41,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -73,179 +76,269 @@ public class TestDrive {
};
private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName());
- private String mAdditionalAllowedPackage;
- private String mDeviceSerial;
- private final Set<Long> mTrackedMetrics = new HashSet<>();
+ @VisibleForTesting
+ String mDeviceSerial = null;
public static void main(String[] args) {
+ final Configuration configuration = new Configuration();
+
TestDrive testDrive = new TestDrive();
- Set<Integer> trackedAtoms = new HashSet<>();
Utils.setUpLogger(LOGGER, false);
- String remoteConfigPath = null;
- if (args.length < 1) {
- LOGGER.log(Level.SEVERE, "Usage: ./test_drive [-p additional_allowed_package] "
- + "[-s DEVICE_SERIAL_NUMBER]"
- + "<atomId1> <atomId2> ... <atomIdN>");
+ if (!testDrive.processArgs(configuration, args,
+ Utils.getDeviceSerials(LOGGER), Utils.getDefaultDevice(LOGGER))) {
return;
}
- List<String> connectedDevices = Utils.getDeviceSerials(LOGGER);
- if (connectedDevices == null || connectedDevices.size() == 0) {
- LOGGER.log(Level.SEVERE, "No device connected.");
- return;
+ final ConfigMetricsReportList reports = testDrive.testDriveAndGetReports(
+ configuration.createConfig(), configuration.hasPulledAtoms(),
+ configuration.hasPushedAtoms());
+ if (reports != null) {
+ configuration.dumpMetrics(reports);
}
+ }
- int arg_index = 0;
- while (arg_index < args.length) {
- String arg = args[arg_index];
- if (arg.equals("-p")) {
- testDrive.mAdditionalAllowedPackage = args[++arg_index];
- } else if (arg.equals("-s")) {
- testDrive.mDeviceSerial = args[++arg_index];
- } else {
- break;
- }
- arg_index++;
+ boolean processArgs(Configuration configuration, String[] args, List<String> connectedDevices,
+ String defaultDevice) {
+ if (args.length < 1) {
+ LOGGER.severe("Usage: ./test_drive [-one] "
+ + "[-p additional_allowed_package] "
+ + "[-s DEVICE_SERIAL_NUMBER] "
+ + "<atomId1> <atomId2> ... <atomIdN>");
+ return false;
}
- if (connectedDevices.size() == 1 && testDrive.mDeviceSerial == null) {
- testDrive.mDeviceSerial = connectedDevices.get(0);
+ int first_arg = 0;
+ // Consume all flags, which must precede all atoms
+ for (; first_arg < args.length; ++first_arg) {
+ String arg = args[first_arg];
+ int remaining_args = args.length - first_arg;
+ if (remaining_args >= 2 && arg.equals("-one")) {
+ LOGGER.info("Creating one event metric to catch all pushed atoms.");
+ configuration.mOnePushedAtomEvent = true;
+ } else if (remaining_args >= 3 && arg.equals("-p")) {
+ configuration.mAdditionalAllowedPackage = args[++first_arg];
+ } else if (remaining_args >= 3 && arg.equals("-s")) {
+ mDeviceSerial = args[++first_arg];
+ } else {
+ break; // Found the atom list
+ }
}
- if (testDrive.mDeviceSerial == null) {
- LOGGER.log(Level.SEVERE, "More than one devices connected. Please specify"
- + " with -s DEVICE_SERIAL");
- return;
+ mDeviceSerial = Utils.chooseDevice(mDeviceSerial, connectedDevices, defaultDevice, LOGGER);
+ if (mDeviceSerial == null) {
+ return false;
}
- for (int i = arg_index; i < args.length; i++) {
+ for ( ; first_arg < args.length; ++first_arg) {
+ String atom = args[first_arg];
try {
- int atomId = Integer.valueOf(args[i]);
- if (Atom.getDescriptor().findFieldByNumber(atomId) == null) {
- LOGGER.log(Level.SEVERE, "No such atom found: " + args[i]);
- continue;
- }
- trackedAtoms.add(atomId);
+ configuration.addAtom(Integer.valueOf(atom));
} catch (NumberFormatException e) {
- LOGGER.log(Level.SEVERE, "Bad atom id provided: " + args[i]);
- continue;
+ LOGGER.severe("Bad atom id provided: " + atom);
}
}
+ return configuration.hasPulledAtoms() || configuration.hasPushedAtoms();
+ }
+
+ private ConfigMetricsReportList testDriveAndGetReports(StatsdConfig config,
+ boolean hasPulledAtoms, boolean hasPushedAtoms) {
+ if (config == null) {
+ LOGGER.severe("Failed to create valid config.");
+ return null;
+ }
+
+ String remoteConfigPath = null;
try {
- StatsdConfig config = testDrive.createConfig(trackedAtoms);
- if (config == null) {
- LOGGER.log(Level.SEVERE, "Failed to create valid config.");
- return;
- }
- remoteConfigPath = testDrive.pushConfig(config, testDrive.mDeviceSerial);
- LOGGER.info("Pushed the following config to statsd:");
+ remoteConfigPath = pushConfig(config, mDeviceSerial);
+ LOGGER.info("Pushed the following config to statsd on device '" + mDeviceSerial
+ + "':");
LOGGER.info(config.toString());
- if (!hasPulledAtom(trackedAtoms)) {
+ if (hasPushedAtoms) {
+ LOGGER.info("Now please play with the device to trigger the event.");
+ }
+ if (!hasPulledAtoms) {
LOGGER.info(
- "Now please play with the device to trigger the event. All events should "
- + "be dumped after 1 min ...");
+ "All events should be dumped after 1 min ...");
Thread.sleep(60_000);
} else {
- LOGGER.info("Now wait for 1.5 minutes ...");
+ LOGGER.info("All events should be dumped after 1.5 minutes ...");
Thread.sleep(15_000);
- Utils.logAppBreadcrumb(0, 0, LOGGER, testDrive.mDeviceSerial);
+ Utils.logAppBreadcrumb(0, 0, LOGGER, mDeviceSerial);
Thread.sleep(75_000);
}
- testDrive.dumpMetrics();
+ return Utils.getReportList(CONFIG_ID, true, false, LOGGER,
+ mDeviceSerial);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to test drive: " + e.getMessage(), e);
} finally {
- testDrive.removeConfig(testDrive.mDeviceSerial);
+ removeConfig(mDeviceSerial);
if (remoteConfigPath != null) {
try {
Utils.runCommand(null, LOGGER,
- "adb", "-s", testDrive.mDeviceSerial, "shell", "rm", remoteConfigPath);
+ "adb", "-s", mDeviceSerial, "shell", "rm",
+ remoteConfigPath);
} catch (Exception e) {
LOGGER.log(Level.WARNING,
"Unable to remove remote config file: " + remoteConfigPath, e);
}
}
}
+ return null;
}
- private void dumpMetrics() throws Exception {
- ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER,
- mDeviceSerial);
- // We may get multiple reports. Take the last one.
- ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
- for (StatsLogReport statsLog : report.getMetricsList()) {
- if (mTrackedMetrics.contains(statsLog.getMetricId())) {
- LOGGER.info(statsLog.toString());
+ static class Configuration {
+ boolean mOnePushedAtomEvent = false;
+ @VisibleForTesting
+ Set<Integer> mPushedAtoms = new TreeSet<>();
+ @VisibleForTesting
+ Set<Integer> mPulledAtoms = new TreeSet<>();
+ @VisibleForTesting
+ String mAdditionalAllowedPackage = null;
+ private final Set<Long> mTrackedMetrics = new HashSet<>();
+
+ private void dumpMetrics(ConfigMetricsReportList reportList) {
+ // We may get multiple reports. Take the last one.
+ ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
+ for (StatsLogReport statsLog : report.getMetricsList()) {
+ if (isTrackedMetric(statsLog.getMetricId())) {
+ LOGGER.info(statsLog.toString());
+ }
}
}
- }
- private StatsdConfig createConfig(Set<Integer> atomIds) {
- long metricId = METRIC_ID_BASE;
- long atomMatcherId = ATOM_MATCHER_ID_BASE;
+ boolean isTrackedMetric(long metricId) {
+ return mTrackedMetrics.contains(metricId);
+ }
- ArrayList<String> allowedSources = new ArrayList<>();
- Collections.addAll(allowedSources, ALLOWED_LOG_SOURCES);
- if (mAdditionalAllowedPackage != null) {
- allowedSources.add(mAdditionalAllowedPackage);
+ static boolean isPulledAtom(int atomId) {
+ return atomId >= PULL_ATOM_START && atomId <= MAX_PLATFORM_ATOM_TAG
+ || atomId >= VENDOR_PULLED_ATOM_START_TAG;
}
- StatsdConfig.Builder builder = StatsdConfig.newBuilder();
- builder
- .addAllAllowedLogSource(allowedSources)
- .addAllDefaultPullPackages(Arrays.asList(DEFAULT_PULL_SOURCES))
- .addPullAtomPackages(PullAtomPackages.newBuilder()
- .setAtomId(Atom.GPU_STATS_GLOBAL_INFO_FIELD_NUMBER)
- .addPackages("AID_GPU_SERVICE"))
- .addPullAtomPackages(PullAtomPackages.newBuilder()
- .setAtomId(Atom.GPU_STATS_APP_INFO_FIELD_NUMBER)
- .addPackages("AID_GPU_SERVICE"))
- .addPullAtomPackages(PullAtomPackages.newBuilder()
- .setAtomId(Atom.TRAIN_INFO_FIELD_NUMBER)
- .addPackages("AID_STATSD"))
- .setHashStringsInMetricReport(false);
-
- if (hasPulledAtom(atomIds)) {
- builder.addAtomMatcher(
- createAtomMatcher(
- Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER, APP_BREADCRUMB_MATCHER_ID));
+ void addAtom(Integer atom) {
+ if (Atom.getDescriptor().findFieldByNumber(atom) == null) {
+ LOGGER.severe("No such atom found: " + atom);
+ return;
+ }
+ if (isPulledAtom(atom)) {
+ mPulledAtoms.add(atom);
+ } else {
+ mPushedAtoms.add(atom);
+ }
}
- for (int atomId : atomIds) {
- if (isPulledAtom(atomId)) {
+ private boolean hasPulledAtoms() {
+ return !mPulledAtoms.isEmpty();
+ }
+
+ private boolean hasPushedAtoms() {
+ return !mPushedAtoms.isEmpty();
+ }
+
+ StatsdConfig createConfig() {
+ long metricId = METRIC_ID_BASE;
+ long atomMatcherId = ATOM_MATCHER_ID_BASE;
+
+ StatsdConfig.Builder builder = baseBuilder();
+
+ if (hasPulledAtoms()) {
+ builder.addAtomMatcher(
+ createAtomMatcher(
+ Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER,
+ APP_BREADCRUMB_MATCHER_ID));
+ }
+
+ for (int atomId : mPulledAtoms) {
builder.addAtomMatcher(createAtomMatcher(atomId, atomMatcherId));
GaugeMetric.Builder gaugeMetricBuilder = GaugeMetric.newBuilder();
gaugeMetricBuilder
- .setId(metricId)
- .setWhat(atomMatcherId)
- .setTriggerEvent(APP_BREADCRUMB_MATCHER_ID)
- .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true).build())
- .setBucket(TimeUnit.ONE_MINUTE)
- .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
- .setMaxNumGaugeAtomsPerBucket(100);
+ .setId(metricId)
+ .setWhat(atomMatcherId)
+ .setTriggerEvent(APP_BREADCRUMB_MATCHER_ID)
+ .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true).build())
+ .setBucket(TimeUnit.ONE_MINUTE)
+ .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
+ .setMaxNumGaugeAtomsPerBucket(100);
builder.addGaugeMetric(gaugeMetricBuilder.build());
- } else {
+ atomMatcherId++;
+ mTrackedMetrics.add(metricId++);
+ }
+
+ // A simple atom matcher for each pushed atom.
+ List<AtomMatcher> simpleAtomMatchers = new ArrayList<>();
+ for (int atomId : mPushedAtoms) {
+ final AtomMatcher atomMatcher = createAtomMatcher(atomId, atomMatcherId++);
+ simpleAtomMatchers.add(atomMatcher);
+ builder.addAtomMatcher(atomMatcher);
+ }
+
+ if (mOnePushedAtomEvent) {
+ // Create a union event metric, using an matcher that matches all pulled atoms.
+ AtomMatcher unionAtomMatcher = createUnionMatcher(simpleAtomMatchers,
+ atomMatcherId);
+ builder.addAtomMatcher(unionAtomMatcher);
EventMetric.Builder eventMetricBuilder = EventMetric.newBuilder();
- eventMetricBuilder
- .setId(metricId)
- .setWhat(atomMatcherId);
+ eventMetricBuilder.setId(metricId).setWhat(unionAtomMatcher.getId());
builder.addEventMetric(eventMetricBuilder.build());
- builder.addAtomMatcher(createAtomMatcher(atomId, atomMatcherId));
+ mTrackedMetrics.add(metricId++);
+ } else {
+ // Create multiple event metrics, one per pulled atom.
+ for (AtomMatcher atomMatcher : simpleAtomMatchers) {
+ EventMetric.Builder eventMetricBuilder = EventMetric.newBuilder();
+ eventMetricBuilder
+ .setId(metricId)
+ .setWhat(atomMatcher.getId());
+ builder.addEventMetric(eventMetricBuilder.build());
+ mTrackedMetrics.add(metricId++);
+ }
}
- atomMatcherId++;
- mTrackedMetrics.add(metricId++);
+
+ return builder.build();
+ }
+
+ private static AtomMatcher createAtomMatcher(int atomId, long matcherId) {
+ AtomMatcher.Builder atomMatcherBuilder = AtomMatcher.newBuilder();
+ atomMatcherBuilder
+ .setId(matcherId)
+ .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder().setAtomId(atomId));
+ return atomMatcherBuilder.build();
}
- return builder.build();
- }
- private static AtomMatcher createAtomMatcher(int atomId, long matcherId) {
- AtomMatcher.Builder atomMatcherBuilder = AtomMatcher.newBuilder();
- atomMatcherBuilder
- .setId(matcherId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder().setAtomId(atomId));
- return atomMatcherBuilder.build();
+ private AtomMatcher createUnionMatcher(List<AtomMatcher> simpleAtomMatchers,
+ long atomMatcherId) {
+ AtomMatcher.Combination.Builder combinationBuilder =
+ AtomMatcher.Combination.newBuilder();
+ combinationBuilder.setOperation(StatsdConfigProto.LogicalOperation.OR);
+ for (AtomMatcher matcher : simpleAtomMatchers) {
+ combinationBuilder.addMatcher(matcher.getId());
+ }
+ AtomMatcher.Builder atomMatcherBuilder = AtomMatcher.newBuilder();
+ atomMatcherBuilder.setId(atomMatcherId).setCombination(combinationBuilder.build());
+ return atomMatcherBuilder.build();
+ }
+
+ private StatsdConfig.Builder baseBuilder() {
+ ArrayList<String> allowedSources = new ArrayList<>();
+ Collections.addAll(allowedSources, ALLOWED_LOG_SOURCES);
+ if (mAdditionalAllowedPackage != null) {
+ allowedSources.add(mAdditionalAllowedPackage);
+ }
+ return StatsdConfig.newBuilder()
+ .addAllAllowedLogSource(allowedSources)
+ .addAllDefaultPullPackages(Arrays.asList(DEFAULT_PULL_SOURCES))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_GLOBAL_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_APP_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.TRAIN_INFO_FIELD_NUMBER)
+ .addPackages("AID_STATSD"))
+ .setHashStringsInMetricReport(false);
+ }
}
private static String pushConfig(StatsdConfig config, String deviceSerial)
@@ -267,21 +360,7 @@ public class TestDrive {
Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial,
"shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID));
} catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Failed to remove config: " + e.getMessage());
- }
- }
-
- private static boolean isPulledAtom(int atomId) {
- return atomId >= PULL_ATOM_START && atomId <= MAX_PLATFORM_ATOM_TAG
- || atomId >= VENDOR_PULLED_ATOM_START_TAG;
- }
-
- private static boolean hasPulledAtom(Set<Integer> atoms) {
- for (Integer i : atoms) {
- if (isPulledAtom(i)) {
- return true;
- }
+ LOGGER.severe("Failed to remove config: " + e.getMessage());
}
- return false;
}
}
diff --git a/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java
new file mode 100644
index 000000000000..b1cc60f74993
--- /dev/null
+++ b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2020 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.statsd.shelltools.testdrive;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for {@link TestDrive}
+ */
+public class ConfigurationTest {
+
+ private StatsdConfigProto.AtomMatcher findAndRemoveAtomMatcherById(
+ List<StatsdConfigProto.AtomMatcher> atomMatchers, long id) {
+ int numMatches = 0;
+ StatsdConfigProto.AtomMatcher match = null;
+ for (StatsdConfigProto.AtomMatcher atomMatcher : atomMatchers) {
+ if (id == atomMatcher.getId()) {
+ ++numMatches;
+ match = atomMatcher;
+ }
+ }
+ if (numMatches == 1) {
+ atomMatchers.remove(match);
+ return match;
+ }
+ return null; // Too many, or not found
+ }
+
+ private final TestDrive.Configuration mConfiguration = new TestDrive.Configuration();
+
+ @Test
+ public void testOnePushed() {
+ final int atom = 90;
+ assertFalse(TestDrive.Configuration.isPulledAtom(atom));
+ mConfiguration.addAtom(atom);
+ StatsdConfig config = mConfiguration.createConfig();
+
+ //event_metric {
+ // id: 1111
+ // what: 1234567
+ //}
+ //atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 90
+ // }
+ //}
+
+ assertEquals(1, config.getEventMetricCount());
+ assertEquals(0, config.getGaugeMetricCount());
+
+ assertTrue(mConfiguration.isTrackedMetric(config.getEventMetric(0).getId()));
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+ assertEquals(atom,
+ findAndRemoveAtomMatcherById(atomMatchers, config.getEventMetric(0).getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(0, atomMatchers.size());
+ }
+
+ @Test
+ public void testOnePulled() {
+ final int atom = 10022;
+ assertTrue(TestDrive.Configuration.isPulledAtom(atom));
+ mConfiguration.addAtom(atom);
+ StatsdConfig config = mConfiguration.createConfig();
+
+ //gauge_metric {
+ // id: 1111
+ // what: 1234567
+ // gauge_fields_filter {
+ // include_all: true
+ // }
+ // bucket: ONE_MINUTE
+ // sampling_type: FIRST_N_SAMPLES
+ // max_num_gauge_atoms_per_bucket: 100
+ // trigger_event: 1111111
+ //}
+ //atom_matcher {
+ // id: 1111111
+ // simple_atom_matcher {
+ // atom_id: 47
+ // }
+ //}
+ //atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 10022
+ // }
+ //}
+
+ assertEquals(0, config.getEventMetricCount());
+ assertEquals(1, config.getGaugeMetricCount());
+
+ assertTrue(mConfiguration.isTrackedMetric(config.getGaugeMetric(0).getId()));
+
+ final StatsdConfigProto.GaugeMetric gaugeMetric = config.getGaugeMetric(0);
+ assertTrue(gaugeMetric.getGaugeFieldsFilter().getIncludeAll());
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+ assertEquals(atom,
+ findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(AtomsProto.Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER,
+ findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getTriggerEvent())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(0, atomMatchers.size());
+ }
+
+ @Test
+ public void testOnePulledTwoPushed() {
+ final int pulledAtom = 10022;
+ assertTrue(TestDrive.Configuration.isPulledAtom(pulledAtom));
+ mConfiguration.addAtom(pulledAtom);
+
+ Integer[] pushedAtoms = new Integer[]{244, 245};
+ for (int atom : pushedAtoms) {
+ assertFalse(TestDrive.Configuration.isPulledAtom(atom));
+ mConfiguration.addAtom(atom);
+ }
+ StatsdConfig config = mConfiguration.createConfig();
+
+ // event_metric {
+ // id: 1111
+ // what: 1234567
+ // }
+ // event_metric {
+ // id: 1112
+ // what: 1234568
+ // }
+ // gauge_metric {
+ // id: 1114
+ // what: 1234570
+ // gauge_fields_filter {
+ // include_all: true
+ // }
+ // bucket: ONE_MINUTE
+ // sampling_type: FIRST_N_SAMPLES
+ // max_num_gauge_atoms_per_bucket: 100
+ // trigger_event: 1111111
+ // }
+ // atom_matcher {
+ // id: 1111111
+ // simple_atom_matcher {
+ // atom_id: 47
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 244
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234568
+ // simple_atom_matcher {
+ // atom_id: 245
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234570
+ // simple_atom_matcher {
+ // atom_id: 10022
+ // }
+ // }
+
+ assertEquals(2, config.getEventMetricCount());
+ assertEquals(1, config.getGaugeMetricCount());
+
+ final StatsdConfigProto.GaugeMetric gaugeMetric = config.getGaugeMetric(0);
+ assertTrue(mConfiguration.isTrackedMetric(gaugeMetric.getId()));
+ assertTrue(gaugeMetric.getGaugeFieldsFilter().getIncludeAll());
+ for (StatsdConfigProto.EventMetric eventMetric : config.getEventMetricList()) {
+ assertTrue(mConfiguration.isTrackedMetric(eventMetric.getId()));
+ }
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+
+ assertEquals(pulledAtom, findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(AtomsProto.Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER,
+ findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getTriggerEvent())
+ .getSimpleAtomMatcher().getAtomId());
+
+ Integer[] actualAtoms = new Integer[]{
+ findAndRemoveAtomMatcherById(atomMatchers, config.getEventMetric(0).getWhat())
+ .getSimpleAtomMatcher().getAtomId(),
+ findAndRemoveAtomMatcherById(atomMatchers, config.getEventMetric(1).getWhat())
+ .getSimpleAtomMatcher().getAtomId()};
+ Arrays.sort(actualAtoms);
+ assertArrayEquals(pushedAtoms, actualAtoms);
+
+ assertEquals(0, atomMatchers.size());
+ }
+
+ @Test
+ public void testOnePulledTwoPushedTogether() {
+ mConfiguration.mOnePushedAtomEvent = true; // Use one event grabbing all pushed atoms
+
+ final int pulledAtom = 10022;
+ assertTrue(TestDrive.Configuration.isPulledAtom(pulledAtom));
+ mConfiguration.addAtom(pulledAtom);
+
+ Integer[] pushedAtoms = new Integer[]{244, 245};
+ for (int atom : pushedAtoms) {
+ assertFalse(TestDrive.Configuration.isPulledAtom(atom));
+ mConfiguration.addAtom(atom);
+ }
+ StatsdConfig config = mConfiguration.createConfig();
+
+ // event_metric {
+ // id: 1112
+ // what: 1234570
+ // }
+ // gauge_metric {
+ // id: 1111
+ // what: 1234567
+ // gauge_fields_filter {
+ // include_all: true
+ // }
+ // bucket: ONE_MINUTE
+ // sampling_type: FIRST_N_SAMPLES
+ // max_num_gauge_atoms_per_bucket: 100
+ // trigger_event: 1111111
+ // }
+ // atom_matcher {
+ // id: 1111111
+ // simple_atom_matcher {
+ // atom_id: 47
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 10022
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234568
+ // simple_atom_matcher {
+ // atom_id: 244
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234569
+ // simple_atom_matcher {
+ // atom_id: 245
+ // }
+ // }
+ // atom_matcher {
+ // id: 1234570
+ // combination {
+ // operation: OR
+ // matcher: 1234568
+ // matcher: 1234569
+ // }
+ // }
+
+ assertEquals(1, config.getEventMetricCount());
+ assertEquals(1, config.getGaugeMetricCount());
+
+ final StatsdConfigProto.GaugeMetric gaugeMetric = config.getGaugeMetric(0);
+ assertTrue(mConfiguration.isTrackedMetric(gaugeMetric.getId()));
+ assertTrue(gaugeMetric.getGaugeFieldsFilter().getIncludeAll());
+
+ StatsdConfigProto.EventMetric eventMetric = config.getEventMetric(0);
+ assertTrue(mConfiguration.isTrackedMetric(eventMetric.getId()));
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+
+ assertEquals(pulledAtom, findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(AtomsProto.Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER,
+ findAndRemoveAtomMatcherById(atomMatchers, gaugeMetric.getTriggerEvent())
+ .getSimpleAtomMatcher().getAtomId());
+
+ StatsdConfigProto.AtomMatcher unionMatcher = findAndRemoveAtomMatcherById(atomMatchers,
+ eventMetric.getWhat());
+ assertNotNull(unionMatcher.getCombination());
+ assertEquals(2, unionMatcher.getCombination().getMatcherCount());
+
+ Integer[] actualAtoms = new Integer[]{
+ findAndRemoveAtomMatcherById(atomMatchers,
+ unionMatcher.getCombination().getMatcher(0))
+ .getSimpleAtomMatcher().getAtomId(),
+ findAndRemoveAtomMatcherById(atomMatchers,
+ unionMatcher.getCombination().getMatcher(1))
+ .getSimpleAtomMatcher().getAtomId()};
+ Arrays.sort(actualAtoms);
+ assertArrayEquals(pushedAtoms, actualAtoms);
+
+ assertEquals(0, atomMatchers.size());
+ }
+}
diff --git a/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java
new file mode 100644
index 000000000000..9d986e7c09cf
--- /dev/null
+++ b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 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.statsd.shelltools.testdrive;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Tests for {@link TestDrive}
+ */
+@RunWith(Parameterized.class)
+public class TestDriveTest {
+ /**
+ * Expected results of a single iteration of the paramerized test.
+ */
+ static class Expect {
+ public boolean success;
+ public Integer[] atoms;
+ public boolean onePushedAtomEvent;
+ public String extraPackage;
+ public String target;
+
+ static Expect success(Integer... atoms) {
+ return new Expect(true, atoms, false, null,
+ TARGET);
+ }
+ Expect(boolean success, Integer[] atoms, boolean onePushedAtomEvent, String extraPackage,
+ String target) {
+ this.success = success;
+ this.atoms = atoms;
+ this.onePushedAtomEvent = onePushedAtomEvent;
+ this.extraPackage = extraPackage;
+ this.target = target;
+ }
+ static final Expect FAILURE = new Expect(false, null,
+ false, null, null);
+ Expect onePushedAtomEvent() {
+ this.onePushedAtomEvent = true;
+ return this;
+ }
+ Expect extraPackage() {
+ this.extraPackage = TestDriveTest.PACKAGE;
+ return this;
+ }
+ }
+
+ @Parameterized.Parameter(0)
+ public String[] mArgs;
+
+ @Parameterized.Parameter(1)
+ public List<String> mConnectedDevices;
+
+ @Parameterized.Parameter(2)
+ public String mDefaultDevice;
+
+ @Parameterized.Parameter(3)
+ public Expect mExpect;
+
+ private static final String TARGET = "target";
+ private static final List<String> TARGET_AND_OTHER = Arrays.asList("otherDevice",
+ TARGET);
+ private static final List<String> TWO_OTHER_DEVICES = Arrays.asList(
+ "other1", "other2");
+ private static final List<String> TARGET_ONLY = Collections.singletonList(TARGET);
+ private static final List<String> NOT_TARGET = Collections.singletonList("other");
+ private static final List<String> NO_DEVICES = Collections.emptyList();
+ private static final String PACKAGE = "extraPackage";
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(
+ new Object[]{new String[]{}, null, null,
+ Expect.FAILURE}, // Usage explanation
+ new Object[]{new String[]{"244", "245"}, null, null,
+ Expect.FAILURE}, // Failure looking up connected devices
+ new Object[]{new String[]{"244", "245"}, NO_DEVICES, null,
+ Expect.FAILURE}, // No connected devices
+ new Object[]{new String[]{"-s", TARGET, "244", "245"}, NOT_TARGET, null,
+ Expect.FAILURE}, // Wrong device connected
+ new Object[]{new String[]{"244", "245"}, TWO_OTHER_DEVICES, null,
+ Expect.FAILURE}, // Wrong devices connected
+ new Object[]{new String[]{"244", "245"}, TARGET_ONLY, null,
+ Expect.success(244, 245)}, // If only one device connected, guess that one
+ new Object[]{new String[]{"244", "not_an_atom"}, TARGET_ONLY, null,
+ Expect.success(244)}, // Ignore non-atoms
+ new Object[]{new String[]{"not_an_atom"}, TARGET_ONLY, null,
+ Expect.FAILURE}, // Require at least one atom
+ new Object[]{new String[]{"244", "245"}, TWO_OTHER_DEVICES, TARGET,
+ Expect.FAILURE}, // ANDROID_SERIAL specifies non-connected target
+ new Object[]{new String[]{"244", "245"}, TARGET_AND_OTHER, TARGET,
+ Expect.success(244, 245)}, // ANDROID_SERIAL specifies a valid target
+ new Object[]{new String[]{"244", "245"}, TARGET_AND_OTHER, null,
+ Expect.FAILURE}, // Two connected devices, no indication of which to use
+ new Object[]{new String[]{"-one", "244", "245"}, TARGET_ONLY, null,
+ Expect.success(244, 245).onePushedAtomEvent()},
+ new Object[]{new String[]{"-p", PACKAGE, "244", "245"}, TARGET_ONLY, null,
+ Expect.success(244, 245).extraPackage()},
+ new Object[]{new String[]{"-p", PACKAGE, "-one", "244", "245"}, TARGET_ONLY, null,
+ Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
+ new Object[]{new String[]{"-one", "-p", PACKAGE, "244", "245"}, TARGET_ONLY, null,
+ Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
+ new Object[]{new String[]{"-s", TARGET, "-one", "-p", PACKAGE, "244", "245"},
+ TARGET_AND_OTHER, null,
+ Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
+ new Object[]{new String[]{"-one", "-s", TARGET, "-p", PACKAGE, "244", "245"},
+ TARGET_AND_OTHER, null,
+ Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
+ new Object[]{new String[]{"-one", "-p", PACKAGE, "-s", TARGET, "244", "245"},
+ TARGET_AND_OTHER, null,
+ Expect.success(244, 245).extraPackage().onePushedAtomEvent()}
+ );
+ }
+
+ private final TestDrive.Configuration mConfiguration = new TestDrive.Configuration();
+ private final TestDrive mTestDrive = new TestDrive();
+
+ private static Integer[] collectAtoms(TestDrive.Configuration configuration) {
+ Integer[] result = new Integer[configuration.mPulledAtoms.size()
+ + configuration.mPushedAtoms.size()];
+ int result_index = 0;
+ for (Integer atom : configuration.mPushedAtoms) {
+ result[result_index++] = atom;
+ }
+ for (Integer atom : configuration.mPulledAtoms) {
+ result[result_index++] = atom;
+ }
+ Arrays.sort(result);
+ return result;
+ }
+
+ @Test
+ public void testProcessArgs() {
+ boolean result = mTestDrive.processArgs(mConfiguration, mArgs, mConnectedDevices,
+ mDefaultDevice);
+ if (mExpect.success) {
+ assertTrue(result);
+ assertArrayEquals(mExpect.atoms, collectAtoms(mConfiguration));
+ assertEquals(mExpect.onePushedAtomEvent, mConfiguration.mOnePushedAtomEvent);
+ assertEquals(mExpect.target, mTestDrive.mDeviceSerial);
+ } else {
+ assertFalse(result);
+ }
+ }
+}