summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2021-10-06 00:31:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-10-06 00:31:53 +0000
commit76a39932afc6e8c2676bf5fbee66db84a84309b3 (patch)
tree0f65c95e55c2dbdfeab4c3bbae85c637c3077e7f
parentcc8cb9d11483ff295d160ccef4806f4d7d343d0f (diff)
parent118cd5eb5618b149d9c382940b3fd2078294a149 (diff)
downloadplatform_testing-76a39932afc6e8c2676bf5fbee66db84a84309b3.tar.gz
Merge "Enable runtime test-level rule injection in microbenchmarks." into sc-dev
-rw-r--r--libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java17
-rw-r--r--libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java102
2 files changed, 114 insertions, 5 deletions
diff --git a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
index e82fd3e18..b6c6f134f 100644
--- a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
+++ b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
@@ -23,6 +23,7 @@ import android.os.BatteryManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.composer.Iterate;
+import android.platform.test.rule.DynamicRuleChain;
import android.platform.test.rule.TracePointRule;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -32,6 +33,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -71,6 +73,10 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
};
@VisibleForTesting static final String MIN_BATTERY_LEVEL_OPTION = "min-battery";
@VisibleForTesting static final String MAX_BATTERY_DRAIN_OPTION = "max-battery-drain";
+ // Use these options to inject rules at runtime via the command line. For details, please see
+ // documentation for DynamicRuleChain.
+ @VisibleForTesting static final String DYNAMIC_OUTER_RULES_OPTION = "outer-rules";
+ @VisibleForTesting static final String DYNAMIC_INNER_RULES_OPTION = "inner-rules";
// Options for aligning with the battery charge (coulomb) counter for power tests. We want to
// start microbenchmarks just after the coulomb counter has decremented to account for the
@@ -275,7 +281,11 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
/** Re-implement the private rules wrapper from {@link BlockJUnit4ClassRunner} in JUnit 4.12. */
private Statement withRules(FrameworkMethod method, Object target, Statement statement) {
Statement result = statement;
- List<TestRule> testRules = getTestRules(target);
+ List<TestRule> testRules = new ArrayList<>();
+ // Inner dynamic rules should be included first because RunRules applies rules inside-out.
+ testRules.add(new DynamicRuleChain(DYNAMIC_INNER_RULES_OPTION, mArguments));
+ testRules.addAll(getTestRules(target));
+ testRules.add(new DynamicRuleChain(DYNAMIC_OUTER_RULES_OPTION, mArguments));
// Apply legacy MethodRules, if they don't overlap with TestRules.
for (org.junit.rules.MethodRule each : rules(target)) {
if (!testRules.contains(each)) {
@@ -283,10 +293,7 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
}
}
// Apply modern, method-level TestRules in outer statements.
- result =
- testRules.isEmpty()
- ? statement
- : new RunRules(result, testRules, describeChild(method));
+ result = new RunRules(result, testRules, describeChild(method));
return result;
}
diff --git a/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java b/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java
index 8d4cd822a..0b44d1aac 100644
--- a/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java
+++ b/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java
@@ -25,10 +25,12 @@ import static org.mockito.Mockito.verify;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.microbenchmark.Microbenchmark.TerminateEarlyException;
+import android.platform.test.rule.TestWatcher;
import android.platform.test.rule.TracePointRule;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -51,6 +53,15 @@ import java.util.List;
*/
@RunWith(JUnit4.class)
public final class MicrobenchmarkTest {
+ // Static logs are needed to validate dynamic rules, which are instantiated reflectively and
+ // cannot access non-static variables.
+ private static List<String> sLogs = new ArrayList<>();
+
+ @Before
+ public void setUp() {
+ sLogs.clear();
+ }
+
/**
* Tests that iterations are respected for microbenchmark tests.
*/
@@ -408,6 +419,57 @@ public final class MicrobenchmarkTest {
}
/**
+ * Test successive iteration will be executed when the terminate on test fail option is
+ * disabled.
+ */
+ @Test
+ public void testDynamicRuleInjection() throws InitializationError {
+ Bundle args = new Bundle();
+ args.putString("iterations", "2");
+ args.putString("rename-iterations", "false");
+ args.putString("terminate-on-test-fail", "false");
+ args.putString(Microbenchmark.DYNAMIC_INNER_RULES_OPTION, LoggingRule1.class.getName());
+ args.putString(Microbenchmark.DYNAMIC_OUTER_RULES_OPTION, LoggingRule2.class.getName());
+ LoggingMicrobenchmark loggingRunner =
+ new LoggingMicrobenchmark(LoggingTestWithRule.class, args);
+ loggingRunner.setOperationLog(sLogs);
+ new JUnitCore().run(loggingRunner);
+ assertThat(sLogs)
+ .containsExactly(
+ "logging rule 2 starting",
+ "hardcoded rule starting",
+ "logging rule 1 starting",
+ "before",
+ "tight before",
+ "begin: testMethod("
+ + "android.platform.test.microbenchmark.MicrobenchmarkTest"
+ + "$LoggingTestWithRule)",
+ "test",
+ "end",
+ "tight after",
+ "after",
+ "logging rule 1 finished",
+ "hardcoded rule finished",
+ "logging rule 2 finished",
+ "logging rule 2 starting",
+ "hardcoded rule starting",
+ "logging rule 1 starting",
+ "before",
+ "tight before",
+ "begin: testMethod("
+ + "android.platform.test.microbenchmark.MicrobenchmarkTest"
+ + "$LoggingTestWithRule)",
+ "test",
+ "end",
+ "tight after",
+ "after",
+ "logging rule 1 finished",
+ "hardcoded rule finished",
+ "logging rule 2 finished")
+ .inOrder();
+ }
+
+ /**
* An extensions of the {@link Microbenchmark} runner that logs the start and end of collecting
* traces. It also passes the operation log to the provided test {@code Class}, if it is a
* {@link LoggingTest}. This is used for ensuring the proper order for evaluating test {@link
@@ -503,10 +565,50 @@ public final class MicrobenchmarkTest {
}
}
+ public static class LoggingTestWithRule extends LoggingTest {
+ @Rule
+ public TestRule hardCodedRule =
+ new TestWatcher() {
+ @Override
+ public void starting(Description description) {
+ sLogs.add("hardcoded rule starting");
+ }
+
+ @Override
+ public void finished(Description description) {
+ sLogs.add("hardcoded rule finished");
+ }
+ };
+ }
+
public static class LoggingFailedTest extends LoggingTest {
@Test
public void testMethod() {
throw new RuntimeException("I failed.");
}
}
+
+ public static class LoggingRule1 extends TestWatcher {
+ @Override
+ public void starting(Description description) {
+ sLogs.add("logging rule 1 starting");
+ }
+
+ @Override
+ public void finished(Description description) {
+ sLogs.add("logging rule 1 finished");
+ }
+ }
+
+ public static class LoggingRule2 extends TestWatcher {
+ @Override
+ public void starting(Description description) {
+ sLogs.add("logging rule 2 starting");
+ }
+
+ @Override
+ public void finished(Description description) {
+ sLogs.add("logging rule 2 finished");
+ }
+ }
}