From 7a4d696bbb27515545f7753bf4c20d1ac7ad684a Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Mon, 29 Apr 2024 11:51:54 -0700 Subject: [PATCH] Saving test artifacts in TAPL when the failure is diagnosed Not waiting for FailureWatcher to catch the exception and save artifacts. This will help to save test artifacts before potential deinitialization in the test which may change the screen contents. Bug: 187761685 Test: presubmit Flag: N/A Change-Id: I7aa95028acfae3fe0895fc5df4ea6f6912fcda52 --- .../quickstep/NavigationModeSwitchRule.java | 5 ++- .../quickstep/TaskbarModeSwitchRule.java | 5 ++- .../launcher3/ui/PortraitLandscapeRunner.java | 2 +- .../launcher3/util/rule/FailureWatcher.java | 31 +++++++++++++++---- .../tapl/LauncherInstrumentation.java | 8 +++++ 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index df88726f68..094fd4c823 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -205,11 +205,10 @@ public class NavigationModeSwitchRule implements TestRule { boolean condition, Description description) { launcher.checkForAnomaly(true, true); if (!condition) { - final AssertionError assertionError = new AssertionError(message); if (description != null) { - FailureWatcher.onError(launcher, description, assertionError); + FailureWatcher.onError(launcher, description); } - throw assertionError; + throw new AssertionError(message); } } } diff --git a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java index e5657fb644..84ceb332d9 100644 --- a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java @@ -130,11 +130,10 @@ public class TaskbarModeSwitchRule implements TestRule { boolean condition, Description description) { launcher.checkForAnomaly(true, true); if (!condition) { - final AssertionError assertionError = new AssertionError(message); if (description != null) { - FailureWatcher.onError(launcher, description, assertionError); + FailureWatcher.onError(launcher, description); } - throw assertionError; + throw new AssertionError(message); } } } diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java index c4e74f20fa..e5c5c196bf 100644 --- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java +++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java @@ -57,7 +57,7 @@ public class PortraitLandscapeRunner implements true)); } catch (Throwable e) { - FailureWatcher.onError(mTest.mLauncher, description, e); + FailureWatcher.onError(mTest.mLauncher, description); throw e; } diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java index 7fba33ec81..7bdc040afc 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java +++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java @@ -30,6 +30,8 @@ import java.util.zip.ZipOutputStream; public class FailureWatcher extends TestWatcher { private static final String TAG = "FailureWatcher"; private static boolean sSavedBugreport = false; + private static Description sDescriptionForLastSavedArtifacts; + private final LauncherInstrumentation mLauncher; @NonNull private final Supplier mViewCaptureDataSupplier; @@ -40,6 +42,18 @@ public class FailureWatcher extends TestWatcher { mViewCaptureDataSupplier = viewCaptureDataSupplier; } + @Override + protected void starting(Description description) { + mLauncher.setOnFailure(() -> onError(mLauncher, description, mViewCaptureDataSupplier)); + super.starting(description); + } + + @Override + protected void finished(Description description) { + super.finished(description); + mLauncher.setOnFailure(null); + } + @Override protected void succeeded(Description description) { super.succeeded(description); @@ -70,7 +84,7 @@ public class FailureWatcher extends TestWatcher { @Override protected void failed(Throwable e, Description description) { - onError(mLauncher, description, e, mViewCaptureDataSupplier); + onError(mLauncher, description, mViewCaptureDataSupplier); } static File diagFile(Description description, String prefix, String ext) { @@ -79,13 +93,18 @@ public class FailureWatcher extends TestWatcher { + description.getMethodName() + "." + ext); } - public static void onError(LauncherInstrumentation launcher, Description description, - Throwable e) { - onError(launcher, description, e, null); + /** Action executed when an error condition is expected. Saves artifacts. */ + public static void onError(LauncherInstrumentation launcher, Description description) { + onError(launcher, description, null); } private static void onError(LauncherInstrumentation launcher, Description description, - Throwable e, @Nullable Supplier viewCaptureDataSupplier) { + @Nullable Supplier viewCaptureDataSupplier) { + if (description.equals(sDescriptionForLastSavedArtifacts)) { + // This test has already saved its artifacts. + return; + } + sDescriptionForLastSavedArtifacts = description; final File sceenshot = diagFile(description, "TestScreenshot", "png"); final File hierarchy = diagFile(description, "Hierarchy", "zip"); @@ -114,7 +133,7 @@ public class FailureWatcher extends TestWatcher { Log.e(TAG, "Failed test " + description.getMethodName() + ",\nscreenshot will be saved to " + sceenshot + ",\nUI dump at: " + hierarchy - + " (use go/web-hv to open the dump file)", e); + + " (use go/web-hv to open the dump file)"); final UiDevice device = launcher.getDevice(); device.takeScreenshot(sceenshot); diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index ba8121f25d..0eaf6a820e 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -204,6 +204,7 @@ public final class LauncherInstrumentation { private Runnable mTestAnomalyChecker; private boolean mCheckEventsForSuccessfulGestures = false; + private Runnable mOnFailure; private Runnable mOnLauncherCrashed; private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE; @@ -342,6 +343,11 @@ public final class LauncherInstrumentation { mCheckEventsForSuccessfulGestures = true; } + /** Sets a runnable that will be invoked upon assertion failures. */ + public void setOnFailure(Runnable onFailure) { + mOnFailure = onFailure; + } + public void setOnLauncherCrashed(Runnable onLauncherCrashed) { mOnLauncherCrashed = onLauncherCrashed; } @@ -623,6 +629,7 @@ public final class LauncherInstrumentation { final String systemAnomalyMessage = getSystemAnomalyMessage(ignoreNavmodeChangeStates, ignoreOnlySystemUiViews); if (systemAnomalyMessage != null) { + if (mOnFailure != null) mOnFailure.run(); Assert.fail(formatSystemHealthMessage(formatErrorWithEvents( "http://go/tapl : Tests are broken by a non-Launcher system error: " + systemAnomalyMessage, false))); @@ -742,6 +749,7 @@ public final class LauncherInstrumentation { void fail(String message) { checkForAnomaly(); + if (mOnFailure != null) mOnFailure.run(); Assert.fail(formatSystemHealthMessage(formatErrorWithEvents( "http://go/tapl test failure: " + message + ";\nContext: " + getContextDescription() + "; now visible state is " + getVisibleStateMessage(), true)));