Skip to content

Fad moving update app functionality to firebaseAppDistribution class #3167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.google.firebase.app.distribution;

import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.AUTHENTICATION_FAILURE;
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE;
import static com.google.firebase.app.distribution.TaskUtils.safeSetTaskException;
import static com.google.firebase.app.distribution.TaskUtils.safeSetTaskResult;

Expand All @@ -41,8 +42,9 @@ public class FirebaseAppDistribution {
private final FirebaseApp firebaseApp;
private final TesterSignInClient testerSignInClient;
private final CheckForNewReleaseClient checkForNewReleaseClient;
private final UpdateAppClient updateAppClient;
private final FirebaseAppDistributionLifecycleNotifier lifecycleNotifier;
private final UpdateApkClient updateApkClient;
private final UpdateAabClient updateAabClient;
private final SignInStorage signInStorage;

private final Object updateIfNewReleaseTaskLock = new Object();
Expand All @@ -65,13 +67,15 @@ public class FirebaseAppDistribution {
@NonNull FirebaseApp firebaseApp,
@NonNull TesterSignInClient testerSignInClient,
@NonNull CheckForNewReleaseClient checkForNewReleaseClient,
@NonNull UpdateAppClient updateAppClient,
@NonNull UpdateApkClient updateApkClient,
@NonNull UpdateAabClient updateAabClient,
@NonNull SignInStorage signInStorage,
@NonNull FirebaseAppDistributionLifecycleNotifier lifecycleNotifier) {
this.firebaseApp = firebaseApp;
this.testerSignInClient = testerSignInClient;
this.checkForNewReleaseClient = checkForNewReleaseClient;
this.updateAppClient = updateAppClient;
this.updateApkClient = updateApkClient;
this.updateAabClient = updateAabClient;
this.signInStorage = signInStorage;
this.lifecycleNotifier = lifecycleNotifier;
lifecycleNotifier.addOnActivityDestroyedListener(this::onActivityDestroyed);
Expand All @@ -88,7 +92,8 @@ public FirebaseAppDistribution(
new TesterSignInClient(firebaseApp, firebaseInstallationsApi, signInStorage),
new CheckForNewReleaseClient(
firebaseApp, new FirebaseAppDistributionTesterApiClient(), firebaseInstallationsApi),
new UpdateAppClient(firebaseApp),
new UpdateApkClient(firebaseApp, new InstallApkClient()),
new UpdateAabClient(),
signInStorage,
lifecycleNotifier);
}
Expand Down Expand Up @@ -240,9 +245,26 @@ private UpdateTask updateApp(boolean showDownloadInNotificationManager) {
Constants.ErrorMessages.AUTHENTICATION_ERROR, AUTHENTICATION_FAILURE));
return updateTask;
}

synchronized (cachedNewReleaseLock) {
return this.updateAppClient.updateApp(cachedNewRelease, showDownloadInNotificationManager);
if (cachedNewRelease == null) {
LogWrapper.getInstance().v("New release not found.");
return getErrorUpdateTask(
new FirebaseAppDistributionException(
Constants.ErrorMessages.NOT_FOUND_ERROR, UPDATE_NOT_AVAILABLE));
}
if (cachedNewRelease.getDownloadUrl() == null) {
LogWrapper.getInstance().v("Download failed to execute");
return getErrorUpdateTask(
new FirebaseAppDistributionException(
Constants.ErrorMessages.DOWNLOAD_URL_NOT_FOUND,
FirebaseAppDistributionException.Status.DOWNLOAD_FAILURE));
}

if (cachedNewRelease.getBinaryType() == BinaryType.AAB) {
return this.updateAabClient.updateAab(cachedNewRelease);
} else {
return this.updateApkClient.updateApk(cachedNewRelease, showDownloadInNotificationManager);
}
}
}

Expand Down Expand Up @@ -383,4 +405,10 @@ private void dismissUpdateDialog() {
updateDialogShown = false;
}
}

private UpdateTask getErrorUpdateTask(Exception e) {
UpdateTaskImpl updateTask = new UpdateTaskImpl();
updateTask.setException(e);
return updateTask;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.AUTHENTICATION_FAILURE;
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.INSTALLATION_CANCELED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -48,10 +50,13 @@
import com.google.firebase.installations.InstallationTokenResult;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
Expand All @@ -66,6 +71,7 @@ public class FirebaseAppDistributionTest {
private static final String TEST_AUTH_TOKEN = "fad.auth.token";
private static final String TEST_IAS_ARTIFACT_ID = "ias-artifact-id";
private static final String IAS_ARTIFACT_ID_KEY = "com.android.vending.internal.apk.id";
private static final String TEST_URL = "https://test-url";
private static final long INSTALLED_VERSION_CODE = 2;

private static final AppDistributionReleaseInternal.Builder TEST_RELEASE_NEWER_AAB_INTERNAL =
Expand All @@ -74,7 +80,7 @@ public class FirebaseAppDistributionTest {
.setDisplayVersion("3.0")
.setReleaseNotes("Newer version.")
.setBinaryType(BinaryType.AAB)
.setDownloadUrl("https://test-url");
.setDownloadUrl(TEST_URL);

private static final AppDistributionRelease TEST_RELEASE_NEWER_AAB =
AppDistributionRelease.builder()
Expand All @@ -84,16 +90,28 @@ public class FirebaseAppDistributionTest {
.setBinaryType(BinaryType.AAB)
.build();

private static final AppDistributionReleaseInternal.Builder TEST_RELEASE_NEWER_APK_INTERNAL =
AppDistributionReleaseInternal.builder()
.setBuildVersion("3")
.setDisplayVersion("3.0")
.setReleaseNotes("Newer version.")
.setBinaryType(BinaryType.APK)
.setDownloadUrl(TEST_URL);

private FirebaseAppDistribution firebaseAppDistribution;
private TestActivity activity;

@Mock private InstallationTokenResult mockInstallationTokenResult;
@Mock private TesterSignInClient mockTesterSignInClient;
@Mock private CheckForNewReleaseClient mockCheckForNewReleaseClient;
@Mock private UpdateAppClient mockUpdateAppClient;
@Mock private InstallApkClient mockInstallApkClient;
private UpdateApkClient mockUpdateApkClient;
@Mock private UpdateAabClient mockUpdateAabClient;
@Mock private SignInStorage mockSignInStorage;
@Mock private FirebaseAppDistributionLifecycleNotifier mockLifecycleNotifier;

Executor testExecutor = Executors.newSingleThreadExecutor();

static class TestActivity extends Activity {}

@Before
Expand All @@ -112,13 +130,17 @@ public void setup() {
.setApiKey(TEST_API_KEY)
.build());

this.mockUpdateApkClient =
Mockito.spy(new UpdateApkClient(testExecutor, firebaseApp, mockInstallApkClient));

firebaseAppDistribution =
spy(
new FirebaseAppDistribution(
firebaseApp,
mockTesterSignInClient,
mockCheckForNewReleaseClient,
mockUpdateAppClient,
mockUpdateApkClient,
mockUpdateAabClient,
mockSignInStorage,
mockLifecycleNotifier));

Expand Down Expand Up @@ -220,7 +242,7 @@ public void updateToNewRelease_whenNewAabReleaseAvailable_showsUpdateDialog() {
AppDistributionReleaseInternal newRelease = TEST_RELEASE_NEWER_AAB_INTERNAL.build();
when(mockCheckForNewReleaseClient.checkForNewRelease()).thenReturn(Tasks.forResult(newRelease));
firebaseAppDistribution.setCachedNewRelease(newRelease);
when(mockUpdateAppClient.updateApp(newRelease, true)).thenReturn(new UpdateTaskImpl());
doReturn(new UpdateTaskImpl()).when(mockUpdateAabClient).updateAab(newRelease);

firebaseAppDistribution.updateIfNewReleaseAvailable();

Expand Down Expand Up @@ -374,9 +396,8 @@ public void updateToNewRelease_receiveProgressUpdateFromUpdateApp() {
AppDistributionReleaseInternal newRelease = TEST_RELEASE_NEWER_AAB_INTERNAL.build();
when(mockCheckForNewReleaseClient.checkForNewRelease()).thenReturn(Tasks.forResult(newRelease));
firebaseAppDistribution.setCachedNewRelease(newRelease);

UpdateTaskImpl mockTask = new UpdateTaskImpl();
when(mockUpdateAppClient.updateApp(newRelease, true)).thenReturn(mockTask);
when(mockUpdateAabClient.updateAab(newRelease)).thenReturn(mockTask);
mockTask.updateProgress(
UpdateProgress.builder()
.setApkFileTotalBytes(1)
Expand Down Expand Up @@ -415,4 +436,45 @@ public void taskCancelledOnScreenRotation() {
assertEquals("Update canceled", e.getMessage());
assertEquals(INSTALLATION_CANCELED, e.getErrorCode());
}

@Test
public void updateAppTask_whenNoReleaseAvailable_throwsError() {
firebaseAppDistribution.setCachedNewRelease(null);
when(mockSignInStorage.getSignInStatus()).thenReturn(true);

UpdateTask updateTask = firebaseAppDistribution.updateApp();

assertFalse(updateTask.isSuccessful());
assertTrue(updateTask.getException() instanceof FirebaseAppDistributionException);
FirebaseAppDistributionException ex =
(FirebaseAppDistributionException) updateTask.getException();
assertEquals(FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE, ex.getErrorCode());
assertEquals(Constants.ErrorMessages.NOT_FOUND_ERROR, ex.getMessage());
}

@Test
public void updateApp_withAabReleaseAvailable_returnsSameAabTask() {
AppDistributionReleaseInternal release = TEST_RELEASE_NEWER_AAB_INTERNAL.build();
firebaseAppDistribution.setCachedNewRelease(release);
UpdateTaskImpl updateTaskToReturn = new UpdateTaskImpl();
doReturn(updateTaskToReturn).when(mockUpdateAabClient).updateAab(release);
when(mockSignInStorage.getSignInStatus()).thenReturn(true);

UpdateTask updateTask = firebaseAppDistribution.updateApp();

assertEquals(updateTask, updateTaskToReturn);
}

@Test
public void updateApp_withApkReleaseAvailable_returnsSameApkTask() {
when(mockSignInStorage.getSignInStatus()).thenReturn(true);
AppDistributionReleaseInternal release = TEST_RELEASE_NEWER_APK_INTERNAL.build();
firebaseAppDistribution.setCachedNewRelease(release);
UpdateTaskImpl updateTaskToReturn = new UpdateTaskImpl();
doReturn(updateTaskToReturn).when(mockUpdateApkClient).updateApk(release, false);

UpdateTask updateTask = firebaseAppDistribution.updateApp();

assertEquals(updateTask, updateTaskToReturn);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,14 @@ public void updateAppTask_onAppResume_setsUpdateCancelled()
assertThrows(FirebaseAppDistributionException.class, onCompleteListener::await);
assertEquals(ReleaseUtils.convertToAppDistributionRelease(newRelease), exception.getRelease());
}

@Test
public void updateApp_whenCalledMultipleTimesWithAAB_returnsSameUpdateTask() {
AppDistributionReleaseInternal newRelease = TEST_RELEASE_NEWER_AAB_INTERNAL.build();

UpdateTask updateTask1 = updateAabClient.updateAab(newRelease);
UpdateTask updateTask2 = updateAabClient.updateAab(newRelease);

assertEquals(updateTask1, updateTask2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,12 @@ public void postProgressUpdate_whenErrorStatus_updatesNotificationsManagerWithEr
updateApkClient.postUpdateProgress(1000, 900, UpdateStatus.DOWNLOADING, false);
assertEquals(0, shadowNotificationManager.size());
}

@Test
public void updateApp_whenCalledMultipleTimesWithApk_returnsSameUpdateTask() {
UpdateTask updateTask1 = updateApkClient.updateApk(TEST_RELEASE, false);
UpdateTask updateTask2 = updateApkClient.updateApk(TEST_RELEASE, false);

assertEquals(updateTask1, updateTask2);
}
}
Loading