Skip to content

Commit b0c4d04

Browse files
committed
DEBUG - add wait on progress listener
1 parent 7098f59 commit b0c4d04

File tree

4 files changed

+93
-4
lines changed

4 files changed

+93
-4
lines changed

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ UpdateTaskImpl updateAab(@NonNull AppDistributionReleaseInternal newRelease) {
9696
// On a background thread, fetch the redirect URL and open it in the Play app
9797
runAsyncInTask(executor, () -> fetchDownloadRedirectUrl(newRelease.getDownloadUrl()))
9898
.onSuccessTask(
99+
executor,
99100
redirectUrl ->
100101
lifecycleNotifier.consumeForegroundActivity(
101102
activity -> openRedirectUrlInPlay(redirectUrl, activity)))

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionLifecycleNotifier.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,14 @@ <T> Task<T> applyToForegroundActivity(ActivityFunction<T> function) {
125125

126126
/** A version of {@link #applyToForegroundActivity} that does not produce a value. */
127127
Task<Void> consumeForegroundActivity(ActivityConsumer consumer) {
128+
System.err.println("DEBUGGING: in consumeForegroundActivity");
128129
return getForegroundActivity()
129130
.onSuccessTask(
130131
// Use direct executor to ensure the consumer is called while Activity is in foreground
131132
DIRECT_EXECUTOR,
132133
activity -> {
133134
try {
135+
System.err.println("DEBUGGING: consuming Foreground activity");
134136
consumer.consume(activity);
135137
return Tasks.forResult(null);
136138
} catch (Throwable t) {

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414
package com.google.firebase.appdistribution.impl;
1515

16+
import static android.os.Looper.getMainLooper;
1617
import static com.google.common.truth.Truth.assertThat;
1718
import static com.google.firebase.appdistribution.impl.TestUtils.assertTaskFailure;
1819
import static com.google.firebase.appdistribution.impl.TestUtils.awaitAsyncOperations;
@@ -36,7 +37,9 @@
3637
import java.util.List;
3738
import java.util.concurrent.ExecutorService;
3839
import java.util.concurrent.Executors;
40+
import java.util.concurrent.TimeoutException;
3941
import javax.net.ssl.HttpsURLConnection;
42+
import junit.framework.AssertionFailedError;
4043
import org.junit.Before;
4144
import org.junit.Test;
4245
import org.junit.runner.RunWith;
@@ -53,6 +56,8 @@
5356
public class AabUpdaterTest {
5457
private static final String TEST_URL = "https://test-url";
5558
private static final String REDIRECT_TO_PLAY = "https://redirect-to-play-url";
59+
private static final int SLEEP_PER_LOOP_MS = 100;
60+
private static final int MAX_LOOPS = 50;
5661

5762
private static final AppDistributionReleaseInternal TEST_RELEASE_NEWER_AAB_INTERNAL =
5863
AppDistributionReleaseInternal.builder()
@@ -143,11 +148,9 @@ public void updateAppTask_emptyLocationHeader_setsDownloadFailure() throws Inter
143148

144149
@Test
145150
public void updateAppTask_whenAabReleaseAvailable_redirectsToPlay() throws Exception {
146-
List<UpdateProgress> progressEvents = new ArrayList<>();
147-
148151
UpdateTask updateTask = aabUpdater.updateAab(TEST_RELEASE_NEWER_AAB_INTERNAL);
149-
updateTask.addOnProgressListener(testExecutor, progressEvents::add);
150-
awaitAsyncOperations(testExecutor);
152+
153+
List<UpdateProgress> progressEvents = awaitProgressUpdates(updateTask, 1);
151154

152155
// Task is not completed in this case, because app is expected to terminate during update
153156
assertThat(shadowActivity.getNextStartedActivity().getData())
@@ -182,4 +185,22 @@ public void updateApp_whenCalledMultipleTimesWithAAB_returnsSameUpdateTask() {
182185

183186
assertEquals(updateTask1, updateTask2);
184187
}
188+
189+
private List<UpdateProgress> awaitProgressUpdates(UpdateTask updateTask, int expectedUpdateCount)
190+
throws InterruptedException, TimeoutException {
191+
List<UpdateProgress> progressEvents = new ArrayList<>();
192+
updateTask.addOnProgressListener(testExecutor, progressEvents::add);
193+
awaitAsyncOperations(testExecutor);
194+
195+
// int loopCount = 0;
196+
// while (progressEvents.size() < expectedUpdateCount && loopCount < MAX_LOOPS) {
197+
// // shadowOf(getMainLooper()).idle();
198+
// Thread.sleep(SLEEP_PER_LOOP_MS);
199+
// loopCount++;
200+
// }
201+
if (progressEvents.size() < expectedUpdateCount) {
202+
throw new TimeoutException(String.format("Timed out waiting for updates (expected = %d, actual = %d)", expectedUpdateCount, progressEvents.size()));
203+
}
204+
return progressEvents;
205+
}
185206
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.appdistribution.impl;
16+
17+
import androidx.annotation.NonNull;
18+
import com.google.android.gms.tasks.OnCanceledListener;
19+
import com.google.android.gms.tasks.OnCompleteListener;
20+
import com.google.android.gms.tasks.Task;
21+
import com.google.firebase.appdistribution.FirebaseAppDistributionException;
22+
import com.google.firebase.appdistribution.OnProgressListener;
23+
import com.google.firebase.appdistribution.UpdateProgress;
24+
import java.io.IOException;
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import java.util.concurrent.CountDownLatch;
28+
import java.util.concurrent.ExecutionException;
29+
import java.util.concurrent.TimeUnit;
30+
31+
/**
32+
* Helper listener that awaits a specific number of progress events on a {@code UpdateTask}.
33+
*
34+
* This works around a limitation of the Tasks API where await() cannot be called on
35+
* the main thread. This listener works around it by running itself on a different thread, thus
36+
* allowing the main thread to be woken up when the Tasks complete.
37+
*
38+
* <p>Note: Calling {@link #await()} from a Robolectric test does block the main thread, since those
39+
* tests are executed on the main thread.
40+
*/
41+
class TestOnProgressListener implements OnProgressListener {
42+
private static final long TIMEOUT_MS = 5000;
43+
private final int expectedProgressCount;
44+
private final CountDownLatch latch;
45+
private final List<UpdateProgress> progressUpdates = new ArrayList<>();
46+
47+
TestOnProgressListener(int expectedProgressCount) {
48+
this.expectedProgressCount = expectedProgressCount;
49+
this.latch = new CountDownLatch(expectedProgressCount);
50+
}
51+
52+
@Override
53+
public void onProgressUpdate(@NonNull UpdateProgress updateProgress) {
54+
progressUpdates.add(updateProgress);
55+
latch.countDown();
56+
}
57+
58+
/** Blocks until the {@link #onProgressUpdate} is called the expected number of times. */
59+
List<UpdateProgress> await() throws InterruptedException {
60+
if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
61+
throw new InterruptedException(String.format("Timed out waiting for progress events (expected = %d, actual = %d)", expectedProgressCount, progressUpdates.size()));
62+
}
63+
return progressUpdates;
64+
}
65+
}

0 commit comments

Comments
 (0)