From a0cb1d55d6910b0c7be082c58dc48b6fe8483d7c Mon Sep 17 00:00:00 2001 From: demolaf Date: Fri, 7 Aug 2026 10:43:23 +0100 Subject: [PATCH 1/2] fix(e2e): retry and fail loudly when clearing Firebase Auth emulator data --- .../firebase/ui/auth/testutil/EmulatorApi.kt | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt b/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt index 4430c37a7..a9ad8c053 100644 --- a/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt +++ b/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt @@ -18,23 +18,38 @@ class EmulatorAuthApi( * This function calls the emulator's clear data endpoint to remove all accounts, * OOB codes, and other authentication data. This ensures test isolation by providing * a clean slate for each test. + * + * Retries on transient failures (e.g. a loaded CI runner momentarily failing to respond) + * and throws if the emulator still can't be cleared, so a broken reset fails the test + * loudly instead of silently leaking stale accounts into the next test. */ fun clearEmulatorData() { - try { - clearAccounts() - } catch (e: Exception) { - println("WARNING: Exception while clearing emulator data: ${e.message}") + val maxRetries = 3 + var lastError: Exception? = null + for (attempt in 1..maxRetries) { + try { + clearAccounts() + return + } catch (e: Exception) { + lastError = e + println("WARNING: Failed to clear emulator data (attempt $attempt/$maxRetries): ${e.message}") + if (attempt < maxRetries) Thread.sleep(500L * attempt) + } } + throw IllegalStateException( + "Failed to clear Firebase Auth Emulator data after $maxRetries attempts. " + + "Aborting test to avoid running against stale emulator state.", + lastError + ) } fun clearAccounts() { httpClient.delete("/emulator/v1/projects/$projectId/accounts") { connection -> val responseCode = connection.responseCode if (responseCode !in 200..299) { - println("WARNING: Failed to clear emulator data: HTTP $responseCode") - } else { - println("TEST: Cleared emulator data") + throw IllegalStateException("Failed to clear emulator data: HTTP $responseCode") } + println("TEST: Cleared emulator data") } } From a304bff3bc10aafc5623df920e258234c47e7c3e Mon Sep 17 00:00:00 2001 From: demolaf Date: Fri, 7 Aug 2026 10:56:35 +0100 Subject: [PATCH 2/2] fix(e2e): don't swallow InterruptedException in emulator clear retry loop --- .../com/firebase/ui/auth/testutil/EmulatorApi.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt b/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt index a9ad8c053..6a2c60e8a 100644 --- a/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt +++ b/e2eTest/src/test/java/com/firebase/ui/auth/testutil/EmulatorApi.kt @@ -30,10 +30,20 @@ class EmulatorAuthApi( try { clearAccounts() return + } catch (e: InterruptedException) { + Thread.currentThread().interrupt() + throw e } catch (e: Exception) { lastError = e println("WARNING: Failed to clear emulator data (attempt $attempt/$maxRetries): ${e.message}") - if (attempt < maxRetries) Thread.sleep(500L * attempt) + if (attempt < maxRetries) { + try { + Thread.sleep(500L * attempt) + } catch (ie: InterruptedException) { + Thread.currentThread().interrupt() + throw ie + } + } } } throw IllegalStateException(