diff options
author | Guang Zhu <guangzhu@google.com> | 2015-05-12 10:37:41 -0700 |
---|---|---|
committer | Guang Zhu <guangzhu@google.com> | 2015-05-12 10:45:18 -0700 |
commit | 392b02203de525e2b14d869031974a23fc8428a2 (patch) | |
tree | 3511abbda723898b5e09973a9b4a434aa118c9f6 | |
parent | b8046de3d836019895807ea4e28504a297d5e844 (diff) | |
download | janktesthelper-392b02203de525e2b14d869031974a23fc8428a2.tar.gz |
support specifying process name at runtime
If the annoated process name with GfxMonitor starts with '#', we
treat it as a method that returns a String to indicate process
name. Such method will be called between beforeTest and test
iteration starts, in case that test class needs to setup test
iteration before it can determine the process name.
Also added monitor class name in the assertion message when not
enough frames are received.
Change-Id: I462f7c10a600372e137eb3d314cbf6703aa14ff5
3 files changed, 47 insertions, 9 deletions
diff --git a/src/main/java/android/support/test/jank/GfxMonitor.java b/src/main/java/android/support/test/jank/GfxMonitor.java index 71ede73..18f283a 100644 --- a/src/main/java/android/support/test/jank/GfxMonitor.java +++ b/src/main/java/android/support/test/jank/GfxMonitor.java @@ -25,7 +25,10 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface GfxMonitor { - /** The name of the process to monitor */ + /** + * The name of the process to monitor. Alternatively, if the name begins with '#', it specifies + * a method that takes no parameters and returns string as the process name to monitor. + * */ String processName(); public static final String KEY_AVG_NUM_JANKY = "gfx-avg-jank"; diff --git a/src/main/java/android/support/test/jank/JankTestBase.java b/src/main/java/android/support/test/jank/JankTestBase.java index bb2605d..a2398c7 100644 --- a/src/main/java/android/support/test/jank/JankTestBase.java +++ b/src/main/java/android/support/test/jank/JankTestBase.java @@ -20,8 +20,8 @@ import android.app.Activity; import android.app.Instrumentation; import android.os.Bundle; import android.support.test.InstrumentationRegistry; -import android.support.test.jank.internal.JankMonitorFactory; import android.support.test.jank.internal.JankMonitor; +import android.support.test.jank.internal.JankMonitorFactory; import android.support.test.runner.AndroidJUnitRunner; import android.test.InstrumentationTestCase; import android.test.InstrumentationTestRunner; @@ -89,14 +89,14 @@ public class JankTestBase extends InstrumentationTestCase { Method afterLoop = resolveMethod(annotation.afterLoop()); Method afterTest = resolveAfterTest(annotation.afterTest()); + // Test setup + beforeTest.invoke(this, (Object[])null); + // Get the appropriate JankMonitors for the test type JankMonitorFactory factory = new JankMonitorFactory(getInstrumentation().getUiAutomation()); - List<JankMonitor> monitors = factory.getJankMonitors(testMethod); + List<JankMonitor> monitors = factory.getJankMonitors(testMethod, this); assertTrue("No monitors configured for this test", monitors.size() > 0); - // Test setup - beforeTest.invoke(this, (Object[])null); - // Execute the test several times according to the "iteration" parameter int iterations = Integer.valueOf(getArguments().getString("iterations", Integer.toString(annotation.defaultIterationCount()))); @@ -117,8 +117,9 @@ public class JankTestBase extends InstrumentationTestCase { int numFrames = monitor.stopIteration(); // Fail the test if we didn't get enough frames - assertTrue(String.format("Too few frames received. Expected: %d, Received: %d.", - annotation.expectedFrames(), numFrames), + assertTrue(String.format( + "Too few frames received. Monitor: %s, Expected: %d, Received: %d.", + monitor.getClass().getSimpleName(), annotation.expectedFrames(), numFrames), numFrames >= annotation.expectedFrames()); } diff --git a/src/main/java/android/support/test/jank/internal/JankMonitorFactory.java b/src/main/java/android/support/test/jank/internal/JankMonitorFactory.java index 55f940d..d3b1cb7 100644 --- a/src/main/java/android/support/test/jank/internal/JankMonitorFactory.java +++ b/src/main/java/android/support/test/jank/internal/JankMonitorFactory.java @@ -18,12 +18,17 @@ package android.support.test.jank.internal; import android.app.UiAutomation; import android.os.Build; +import android.support.test.jank.JankTestBase; import android.support.test.jank.WindowAnimationFrameStatsMonitor; import android.support.test.jank.WindowContentFrameStatsMonitor; import android.support.test.jank.GfxMonitor; import android.util.Log; +import junit.framework.Assert; + +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; @@ -40,7 +45,7 @@ public class JankMonitorFactory { mUiAutomation = automation; } - public List<JankMonitor> getJankMonitors(Method testMethod) { + public List<JankMonitor> getJankMonitors(Method testMethod, JankTestBase testInstance) { List<JankMonitor> monitors = new ArrayList<JankMonitor>(); if (testMethod.getAnnotation(GfxMonitor.class) != null) { // GfxMonitor only works on M+. NB: Hard coding value since SDK 22 isn't in prebuilts. @@ -48,6 +53,35 @@ public class JankMonitorFactory { Log.w(TAG, "Skipping GfxMonitor. Not supported by current platform."); } else { String process = testMethod.getAnnotation(GfxMonitor.class).processName(); + // if process name starts with "#", treat it as a method that returns process name + if (process.startsWith("#")) { + process = process.substring(1); + Method method = null; + try { + method = testMethod.getDeclaringClass().getMethod(process, (Class[]) null); + } catch (NoSuchMethodException e) { + Assert.fail(String.format("Method \"%s\" not found", process)); + } + + if (!Modifier.isPublic(method.getModifiers())) { + Assert.fail(String.format("Method \"%s\" should be public", process)); + } + + Object o = null; + try { + o = method.invoke(testInstance, (Object[])null); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + Assert.fail(String.format( + "Exception %s(%s) while invoking \"%s\" for monitored process name", + e.getClass().getName(), e.getMessage(), process)); + } + if (o == null || !(o instanceof String)) { + Assert.fail(String.format("Method \"%s\" should return String", process)); + } + process = (String)o; + Log.d(TAG, "Using process name from annotated method: " + process); + } monitors.add(new GfxMonitorImpl(mUiAutomation, process)); } } |