Bug 1465480 - Throw away cached session if there was a crash r=jchen draft
authorJames Willcox <snorp@snorp.net>
Wed, 30 May 2018 13:09:46 -0500
changeset 804893 f997e7c7168d674d0c009fde87512899ce3e605b
parent 804892 a4091f3021053e2c992959a0b35b26f1c34fd339
child 804894 6b35cd1a9d4016b7f411abf3640361d3fa156ee3
push id112488
push userbmo:snorp@snorp.net
push dateWed, 06 Jun 2018 17:59:13 +0000
reviewersjchen
bugs1465480
milestone62.0a1
Bug 1465480 - Throw away cached session if there was a crash r=jchen If a content process crashes during a test, throw away the cached session since it may be in an inconsistent state. MozReview-Commit-ID: 9bqWNeJjYd5
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
@@ -1127,16 +1127,17 @@ public class GeckoSessionTestRule extend
 
     protected void prepareStatement(final Description description) throws Throwable {
         final GeckoSessionSettings settings = new GeckoSessionSettings(mDefaultSettings);
         mTimeoutMillis = getDefaultTimeoutMillis();
         mNullDelegates = new HashSet<>();
         mClosedSession = false;
         mWithDevTools = false;
         mReuseSession = true;
+        mIgnoreCrash = false;
 
         applyAnnotations(Arrays.asList(description.getTestClass().getAnnotations()), settings);
         applyAnnotations(description.getAnnotations(), settings);
 
         final List<CallRecord> records = new ArrayList<>();
         final CallbackDelegates waitDelegates = new CallbackDelegates();
         final CallbackDelegates testDelegates = new CallbackDelegates();
         mCallRecords = records;
@@ -1159,20 +1160,16 @@ public class GeckoSessionTestRule extend
                         case "toString":
                             return "Call Recorder";
                     }
                     ignore = true;
                 } else if (mCallRecordHandler != null) {
                     ignore = mCallRecordHandler.handleCall(method, args);
                 }
 
-                if (!mIgnoreCrash && sOnCrash.equals(method)) {
-                    throw new RuntimeException("Content process crashed");
-                }
-
                 final boolean isExternalDelegate =
                         !DEFAULT_DELEGATES.contains(method.getDeclaringClass());
 
                 if (!ignore) {
                     assertThat("Callbacks must be on UI thread",
                                Looper.myLooper(), equalTo(Looper.getMainLooper()));
 
                     final GeckoSession session;
@@ -1180,16 +1177,21 @@ public class GeckoSessionTestRule extend
                         session = null;
                     } else {
                         assertThat("Callback first argument must be session object",
                                    args, arrayWithSize(greaterThan(0)));
                         assertThat("Callback first argument must be session object",
                                    args[0], instanceOf(GeckoSession.class));
                         session = (GeckoSession) args[0];
                     }
+
+                    if (sOnCrash.equals(method) && !mIgnoreCrash && isUsingSession(session)) {
+                        throw new RuntimeException("Content process crashed");
+                    }
+
                     records.add(new CallRecord(session, method, args));
 
                     call = waitDelegates.prepareMethodCall(session, method);
                     if (call == null) {
                         call = testDelegates.prepareMethodCall(session, method);
                     }
 
                     if (isExternalDelegate) {
@@ -1244,16 +1246,20 @@ public class GeckoSessionTestRule extend
                     .javaCrashReportingEnabled(true)
                     .remoteDebuggingEnabled(true);
 
             sRuntime = GeckoRuntime.create(
                 InstrumentationRegistry.getTargetContext(),
                 runtimeSettingsBuilder.build());
         }
 
+        if (sCachedSession != null && !sCachedSession.isOpen()) {
+            sCachedSession = null;
+        }
+
         final boolean useDefaultSession = !mClosedSession && mDefaultSettings.equals(settings);
         if (useDefaultSession && mReuseSession && sCachedSession != null) {
             mMainSession = sCachedSession;
         } else {
             mMainSession = new GeckoSession(settings);
         }
         prepareSession(mMainSession);
 
@@ -1359,33 +1365,45 @@ public class GeckoSessionTestRule extend
     public void performTestEndCheck() {
         mWaitScopeDelegates.clearAndAssert();
         mTestScopeDelegates.clearAndAssert();
     }
 
     protected void cleanupSession(final GeckoSession session) {
         final Tab tab = (mRDPTabs != null) ? mRDPTabs.get(session) : null;
         if (tab != null) {
-            tab.getPromises().detach();
-            tab.detach();
+            if (session.isOpen()) {
+                tab.getPromises().detach();
+                tab.detach();
+            }
+
             mRDPTabs.remove(session);
         }
         if (session.isOpen()) {
             session.close();
         }
     }
 
+    protected boolean isUsingSession(final GeckoSession session) {
+        return session.equals(mMainSession) || mSubSessions.contains(session);
+    }
+
     protected void cleanupStatement() throws Throwable {
         mWaitScopeDelegates.clear();
         mTestScopeDelegates.clear();
 
         for (final GeckoSession session : mSubSessions) {
             cleanupSession(session);
         }
-        if (mMainSession.equals(sCachedSession)) {
+
+        if (sCachedSession != null && mReuseSession && !mIgnoreCrash) {
+            assertThat("Cached session should be open", sCachedSession.isOpen(), equalTo(true));
+        }
+
+        if (mMainSession.isOpen() && mMainSession.equals(sCachedSession)) {
             // We have to detach the Promises object, but keep the Tab itself.
             sCachedRDPTab.getPromises().detach();
         } else {
             cleanupSession(mMainSession);
         }
 
         if (mDisplay != null) {
             mDisplay.surfaceDestroyed();