Catch test rule execution errors in FlickerServiceJUnitRunner

This is to avoid causing module errors when the test rule fails to execute

Bug: 405922310
Test: atest android.tools.flicker.junit.FlickerServiceJUnit4ClassRunnerTest
Flag: TEST_ONLY
Change-Id: I1505d0c71b20bdebee9b385fc1ab11af228e3b12
diff --git a/libraries/flicker/src/android/tools/flicker/junit/FlickerServiceDecorator.kt b/libraries/flicker/src/android/tools/flicker/junit/FlickerServiceDecorator.kt
index 444685d..10210e0 100644
--- a/libraries/flicker/src/android/tools/flicker/junit/FlickerServiceDecorator.kt
+++ b/libraries/flicker/src/android/tools/flicker/junit/FlickerServiceDecorator.kt
@@ -193,14 +193,22 @@
                                 }
                             }
                         }
-                    ruleContainer
-                        .apply(
-                            method,
-                            description,
-                            testClass.onlyConstructor.newInstance(),
-                            statement,
-                        )
-                        .evaluate()
+
+                    try {
+                        ruleContainer
+                            .apply(
+                                method,
+                                description,
+                                testClass.onlyConstructor.newInstance(),
+                                statement,
+                            )
+                            .evaluate()
+                    } catch (e: Throwable) {
+                        // Failed to execute test rules, report the error in the test method's
+                        // result instead of causing a module failure due to crashing in the
+                        // getTestMethods method.
+                        innerMethodsResults[method] = e
+                    }
                 }
 
                 if (innerMethodsResults[method] == null) {
diff --git a/libraries/flicker/test/src/android/tools/flicker/junit/FlickerServiceJUnit4ClassRunnerTest.kt b/libraries/flicker/test/src/android/tools/flicker/junit/FlickerServiceJUnit4ClassRunnerTest.kt
index be5ea7b..bdcf95b 100644
--- a/libraries/flicker/test/src/android/tools/flicker/junit/FlickerServiceJUnit4ClassRunnerTest.kt
+++ b/libraries/flicker/test/src/android/tools/flicker/junit/FlickerServiceJUnit4ClassRunnerTest.kt
@@ -37,6 +37,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth
 import java.time.Instant
+import org.junit.Assert
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestRule
@@ -135,6 +136,28 @@
             .fireTestFinished(ArgumentMatchers.argThat { it.methodName.contains("FaaS") })
     }
 
+    @Test
+    fun reportsTestRuleFailureInTest() {
+        var testRan = false
+        onTestRuleStart = Runnable { Assert.fail("Test rule failed") }
+        onTestStart = Runnable { testRan = true }
+
+        val runner = FlickerServiceJUnit4ClassRunner(SimpleTest::class.java)
+        val notifier = Mockito.mock(RunNotifier::class.java)
+        runner.run(notifier)
+
+        Truth.assertThat(testRan).isFalse()
+
+        Truth.assertThat(runner.testCount()).isEqualTo(1)
+        Mockito.verify(notifier)
+            .fireTestFailure(
+                ArgumentMatchers.argThat {
+                    it.description.methodName.equals("test") &&
+                        it.message.contains("Test rule failed")
+                }
+            )
+    }
+
     /** Below are all the mock test classes uses for testing purposes */
     @RunWith(FlickerServiceJUnit4ClassRunner::class)
     open class SimpleTest {