Skip to content

Commit 6a1fa5f

Browse files
authored
Merge 385d2cc into 8c83cfc
2 parents 8c83cfc + 385d2cc commit 6a1fa5f

File tree

3 files changed

+53
-52
lines changed

3 files changed

+53
-52
lines changed

firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/ApkUpdaterTest.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
package com.google.firebase.appdistribution.impl;
1616

1717
import static com.google.common.truth.Truth.assertThat;
18-
import static com.google.firebase.appdistribution.impl.TestUtils.awaitProgressEvents;
18+
import static com.google.firebase.appdistribution.impl.TestUtils.awaitCondition;
1919
import static com.google.firebase.appdistribution.impl.TestUtils.awaitTask;
2020
import static org.junit.Assert.assertThrows;
2121
import static org.mockito.ArgumentMatchers.any;
@@ -42,6 +42,7 @@
4242
import com.google.firebase.appdistribution.UpdateProgress;
4343
import com.google.firebase.appdistribution.UpdateStatus;
4444
import com.google.firebase.appdistribution.UpdateTask;
45+
import com.google.firebase.concurrent.FirebaseExecutors;
4546
import com.google.firebase.concurrent.TestOnlyExecutors;
4647
import java.io.ByteArrayInputStream;
4748
import java.io.File;
@@ -179,19 +180,18 @@ public void updateApk_whenCannotReadInputStream_setsDownloadFailure() throws Exc
179180

180181
@Test
181182
public void updateApk_whenSuccessfullyUpdated_notificationsSetCorrectly()
182-
throws FirebaseAppDistributionException, ExecutionException, InterruptedException,
183-
IOException {
183+
throws FirebaseAppDistributionException, InterruptedException, IOException {
184184
doReturn(new ByteArrayInputStream(TEST_FILE.getBytes()))
185185
.when(mockHttpsUrlConnection)
186186
.getInputStream();
187187
// Block thread actually making the request on a latch, which gives us time to add listeners to
188188
// the returned UpdateTask in time to get all the progress updates
189-
CountDownLatch mockConnectionLatch = new CountDownLatch(1);
189+
CountDownLatch countDownLatch = new CountDownLatch(1);
190190
when(mockHttpsUrlConnectionFactory.openConnection(TEST_URL))
191191
.thenAnswer(
192192
invocation -> {
193193
try {
194-
mockConnectionLatch.await();
194+
countDownLatch.await();
195195
} catch (InterruptedException e) {
196196
throw new AssertionError("Interrupted while waiting in mock");
197197
}
@@ -200,11 +200,15 @@ public void updateApk_whenSuccessfullyUpdated_notificationsSetCorrectly()
200200
doNothing().when(apkUpdater).validateJarFile(any(), anyLong(), anyBoolean(), anyLong());
201201
when(mockApkInstaller.installApk(any(), any())).thenReturn(Tasks.forResult(null));
202202

203+
// Start the update
203204
UpdateTask updateTask = apkUpdater.updateApk(TEST_RELEASE, true);
204-
List<UpdateProgress> events =
205-
awaitProgressEvents(updateTask, 3, mockConnectionLatch::countDown);
206205

207-
assertThat(events).hasSize(3);
206+
// Listen for progress events
207+
List<UpdateProgress> events = new ArrayList<>();
208+
updateTask.addOnProgressListener(FirebaseExecutors.directExecutor(), events::add);
209+
countDownLatch.countDown();
210+
awaitCondition(() -> events.size() == 3);
211+
208212
assertThat(events.get(0).getUpdateStatus()).isEqualTo(UpdateStatus.PENDING);
209213
assertThat(events.get(1).getUpdateStatus()).isEqualTo(UpdateStatus.DOWNLOADING);
210214
assertThat(events.get(1).getApkBytesDownloaded()).isEqualTo(TEST_FILE.length());

firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionServiceImplTest.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import static com.google.firebase.appdistribution.impl.FeedbackActivity.RELEASE_NAME_KEY;
3434
import static com.google.firebase.appdistribution.impl.FeedbackActivity.SCREENSHOT_URI_KEY;
3535
import static com.google.firebase.appdistribution.impl.TestUtils.awaitAsyncOperations;
36-
import static com.google.firebase.appdistribution.impl.TestUtils.awaitProgressEvents;
36+
import static com.google.firebase.appdistribution.impl.TestUtils.awaitCondition;
3737
import static com.google.firebase.appdistribution.impl.TestUtils.awaitTask;
3838
import static com.google.firebase.appdistribution.impl.TestUtils.awaitTaskFailure;
3939
import static com.google.firebase.appdistribution.impl.TestUtils.awaitTermination;
@@ -86,6 +86,7 @@
8686
import com.google.firebase.installations.InstallationTokenResult;
8787
import java.util.ArrayList;
8888
import java.util.List;
89+
import java.util.concurrent.CountDownLatch;
8990
import java.util.concurrent.ExecutionException;
9091
import java.util.concurrent.ExecutorService;
9192
import java.util.concurrent.Executors;
@@ -364,11 +365,29 @@ public void updateIfNewReleaseAvailable_whenNoReleaseAvailable_updateDialogNotSh
364365
@Test
365366
public void updateIfNewReleaseAvailable_whenActivityBackgrounded_updateDialogNotShown()
366367
throws InterruptedException {
367-
when(mockNewReleaseFetcher.checkForNewRelease()).thenReturn(Tasks.forResult(null));
368-
368+
// Block thread making the request on a latch, which gives us time to add listeners to the
369+
// returned UpdateTask in time to get all the progress updates
370+
CountDownLatch countDownLatch = new CountDownLatch(1);
371+
when(mockNewReleaseFetcher.checkForNewRelease())
372+
.thenAnswer(
373+
invocation -> {
374+
try {
375+
countDownLatch.await();
376+
} catch (InterruptedException e) {
377+
throw new AssertionError("Interrupted while waiting in mock");
378+
}
379+
return Tasks.forResult(null);
380+
});
381+
382+
// Start the update
369383
UpdateTask task = firebaseAppDistribution.updateIfNewReleaseAvailable();
370384

371-
List<UpdateProgress> progressEvents = awaitProgressEvents(task, 1);
385+
// Listen for progress events
386+
List<UpdateProgress> progressEvents = new ArrayList<>();
387+
task.addOnProgressListener(FirebaseExecutors.directExecutor(), progressEvents::add);
388+
countDownLatch.countDown();
389+
awaitCondition(() -> progressEvents.size() == 1);
390+
372391
assertEquals(UpdateStatus.NEW_RELEASE_NOT_AVAILABLE, progressEvents.get(0).getUpdateStatus());
373392
assertNull(ShadowAlertDialog.getLatestAlertDialog());
374393
}

firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/TestUtils.java

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,25 @@
2828
import com.google.android.gms.tasks.Tasks;
2929
import com.google.firebase.appdistribution.FirebaseAppDistributionException;
3030
import com.google.firebase.appdistribution.FirebaseAppDistributionException.Status;
31-
import com.google.firebase.appdistribution.UpdateProgress;
32-
import com.google.firebase.appdistribution.UpdateTask;
3331
import com.google.firebase.appdistribution.impl.FirebaseAppDistributionLifecycleNotifier.ActivityConsumer;
3432
import com.google.firebase.appdistribution.impl.FirebaseAppDistributionLifecycleNotifier.ActivityFunction;
35-
import com.google.firebase.concurrent.FirebaseExecutors;
36-
import com.google.firebase.concurrent.TestOnlyExecutors;
3733
import java.io.IOException;
3834
import java.io.InputStream;
39-
import java.util.ArrayList;
40-
import java.util.List;
4135
import java.util.concurrent.ExecutionException;
4236
import java.util.concurrent.ExecutorService;
4337
import java.util.concurrent.Executors;
4438
import java.util.concurrent.TimeUnit;
39+
import java.util.function.BooleanSupplier;
4540
import org.json.JSONException;
4641
import org.json.JSONObject;
4742
import org.mockito.stubbing.Answer;
4843

4944
final class TestUtils {
45+
46+
private static final int AWAIT_TERMINATION_TIMEOUT_MS = 100;
47+
private static final int AWAIT_CONDITION_TIMEOUT_MS = 500;
48+
private static final int SLEEP_MS = 50;
49+
5050
private TestUtils() {}
5151

5252
static void awaitTaskFailure(Task task, Status status, String messageSubstring) {
@@ -89,7 +89,7 @@ static <T> T awaitTask(Task<T> task)
8989
}
9090

9191
static void awaitTermination(ExecutorService executorService) throws InterruptedException {
92-
executorService.awaitTermination(100, TimeUnit.MILLISECONDS);
92+
executorService.awaitTermination(AWAIT_TERMINATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
9393
}
9494

9595
static void awaitAsyncOperations(ExecutorService executorService) throws InterruptedException {
@@ -101,41 +101,19 @@ static void awaitAsyncOperations(ExecutorService executorService) throws Interru
101101
shadowOf(getMainLooper()).idle();
102102
}
103103

104-
/** Await a specified number of progress events on an {@link UpdateTask}. */
105-
static List<UpdateProgress> awaitProgressEvents(UpdateTask updateTask, int count)
106-
throws InterruptedException {
107-
return awaitProgressEvents(updateTask, count, /* setupFunction= */ () -> {});
104+
static void awaitCondition(BooleanSupplier condition) throws InterruptedException {
105+
long start = System.currentTimeMillis();
106+
while (elapsedTime(start) < AWAIT_CONDITION_TIMEOUT_MS) {
107+
if (condition.getAsBoolean()) {
108+
return;
109+
}
110+
Thread.sleep(SLEEP_MS);
111+
}
112+
throw new AssertionError("Timed out waiting for condition");
108113
}
109114

110-
/**
111-
* Await a specified number of progress events on an {@link UpdateTask}, executing a {@link
112-
* Runnable} after adding the listeners.
113-
*
114-
* @param updateTask the update task
115-
* @param count the number of progress events to await
116-
* @param setupFunction a function to run after adding the listeners to the update task, but
117-
* before we await the progress events. This is useful for kicking off delayed processes that
118-
* would otherwise start emitting progress events that need to be captured.
119-
*/
120-
static List<UpdateProgress> awaitProgressEvents(
121-
UpdateTask updateTask, int count, Runnable setupFunction) throws InterruptedException {
122-
List<UpdateProgress> progressEvents = new ArrayList<>();
123-
updateTask.addOnProgressListener(FirebaseExecutors.directExecutor(), progressEvents::add);
124-
setupFunction.run();
125-
ExecutorService executor = TestOnlyExecutors.blocking();
126-
executor.execute(
127-
() -> {
128-
while (progressEvents.size() < count) {
129-
try {
130-
Thread.sleep(50);
131-
} catch (InterruptedException e) {
132-
throw new RuntimeException("Interrupted while waiting for progress events", e);
133-
}
134-
}
135-
});
136-
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
137-
assertThat(progressEvents).hasSize(count);
138-
return progressEvents;
115+
private static long elapsedTime(long start) {
116+
return System.currentTimeMillis() - start;
139117
}
140118

141119
/**

0 commit comments

Comments
 (0)