From ef24e952999f28f452f165a096a4a5436983dae2 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 11 Aug 2025 18:27:01 +0000 Subject: [PATCH] appdistribution: fix flaky test due to race condtion in testing logic: checkForNewRelease_whenCalledMultipleTimes_onlyFetchesReleasesOnce --- .../firebase/appdistribution/impl/TaskCache.java | 15 +++++++++++++++ .../impl/NewReleaseFetcherTest.java | 1 + 2 files changed, 16 insertions(+) diff --git a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/TaskCache.java b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/TaskCache.java index b370aea77de..ee99cd8eb09 100644 --- a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/TaskCache.java +++ b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/TaskCache.java @@ -14,6 +14,7 @@ package com.google.firebase.appdistribution.impl; +import androidx.annotation.VisibleForTesting; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; import com.google.firebase.annotations.concurrent.Lightweight; @@ -66,6 +67,20 @@ Task getOrCreateTask(TaskProducer producer) { return taskCompletionSource.getTask(); } + /** + * Returns a task that completes when this object's internal sequential executor has finished + * processing all enqueued operations. + *

+ * This method should never be called in production code; however, it is useful in unit tests to + * ensure deterministic behavior. + */ + @VisibleForTesting + Task newTaskForSequentialExecutorFlush() { + TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + sequentialExecutor.execute(() -> taskCompletionSource.setResult(null)); + return taskCompletionSource.getTask(); + } + private static boolean isOngoing(Task task) { return task != null && !task.isComplete(); } diff --git a/firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/NewReleaseFetcherTest.java b/firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/NewReleaseFetcherTest.java index 84e67c747eb..df69e582615 100644 --- a/firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/NewReleaseFetcherTest.java +++ b/firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/NewReleaseFetcherTest.java @@ -112,6 +112,7 @@ public void checkForNewRelease_whenCalledMultipleTimes_onlyFetchesReleasesOnce() // Don't set the result until after calling twice, to make sure that the task from the first // call is still ongoing. + awaitTask(newReleaseFetcher.cachedCheckForNewRelease.newTaskForSequentialExecutorFlush()); task.setResult(null); awaitTask(checkForNewReleaseTask1); awaitTask(checkForNewReleaseTask2);