14
14
15
15
package com .google .firebase .appdistribution .impl ;
16
16
17
+ import static android .content .Context .MODE_PRIVATE ;
17
18
import static android .os .Looper .getMainLooper ;
18
19
import static com .google .common .truth .Truth .assertThat ;
19
20
import static com .google .firebase .appdistribution .FirebaseAppDistributionException .Status .AUTHENTICATION_CANCELED ;
43
44
import static org .junit .Assert .assertNull ;
44
45
import static org .junit .Assert .assertTrue ;
45
46
import static org .mockito .ArgumentMatchers .any ;
46
- import static org .mockito .ArgumentMatchers .anyBoolean ;
47
47
import static org .mockito .Mockito .doReturn ;
48
48
import static org .mockito .Mockito .never ;
49
49
import static org .mockito .Mockito .spy ;
58
58
import android .app .Dialog ;
59
59
import android .content .DialogInterface ;
60
60
import android .content .Intent ;
61
+ import android .content .SharedPreferences ;
61
62
import android .content .pm .ApplicationInfo ;
62
63
import android .content .pm .PackageInfo ;
63
64
import android .net .Uri ;
70
71
import com .google .android .gms .tasks .Tasks ;
71
72
import com .google .firebase .FirebaseApp ;
72
73
import com .google .firebase .FirebaseOptions ;
74
+ import com .google .firebase .annotations .concurrent .Background ;
73
75
import com .google .firebase .annotations .concurrent .Blocking ;
74
76
import com .google .firebase .annotations .concurrent .Lightweight ;
75
77
import com .google .firebase .appdistribution .AppDistributionRelease ;
@@ -143,18 +145,18 @@ public class FirebaseAppDistributionServiceImplTest {
143
145
144
146
@ Lightweight private final ExecutorService lightweightExecutor = TestOnlyExecutors .lite ();
145
147
@ Blocking private final ExecutorService blockingExecutor = TestOnlyExecutors .blocking ();
148
+ @ Background private final ExecutorService backgroundExecutor = TestOnlyExecutors .background ();
146
149
147
150
private FirebaseAppDistributionImpl firebaseAppDistribution ;
148
151
private ActivityController <TestActivity > activityController ;
149
152
private TestActivity activity ;
150
- private FirebaseApp firebaseApp ;
151
153
152
154
@ Mock private InstallationTokenResult mockInstallationTokenResult ;
153
155
@ Mock private TesterSignInManager mockTesterSignInManager ;
154
156
@ Mock private NewReleaseFetcher mockNewReleaseFetcher ;
155
157
@ Mock private ApkUpdater mockApkUpdater ;
156
158
@ Mock private AabUpdater mockAabUpdater ;
157
- @ Mock private SignInStorage mockSignInStorage ;
159
+ @ Mock private SignInStorage signInStorage ;
158
160
@ Mock private FirebaseAppDistributionLifecycleNotifier mockLifecycleNotifier ;
159
161
@ Mock private ReleaseIdentifier mockReleaseIdentifier ;
160
162
@ Mock private ScreenshotTaker mockScreenshotTaker ;
@@ -168,7 +170,10 @@ public void setup() throws FirebaseAppDistributionException {
168
170
169
171
FirebaseApp .clearInstancesForTest ();
170
172
171
- firebaseApp =
173
+ signInStorage =
174
+ spy (new SignInStorage (ApplicationProvider .getApplicationContext (), backgroundExecutor ));
175
+
176
+ FirebaseApp firebaseApp =
172
177
FirebaseApp .initializeApp (
173
178
ApplicationProvider .getApplicationContext (),
174
179
new FirebaseOptions .Builder ()
@@ -185,16 +190,15 @@ public void setup() throws FirebaseAppDistributionException {
185
190
mockNewReleaseFetcher ,
186
191
mockApkUpdater ,
187
192
mockAabUpdater ,
188
- mockSignInStorage ,
193
+ signInStorage ,
189
194
mockLifecycleNotifier ,
190
195
mockReleaseIdentifier ,
191
196
mockScreenshotTaker ,
192
197
lightweightExecutor ,
193
198
blockingExecutor ));
194
199
195
200
when (mockTesterSignInManager .signInTester ()).thenReturn (Tasks .forResult (null ));
196
- when (mockSignInStorage .getSignInStatus ()).thenReturn (Tasks .forResult (true ));
197
- when (mockSignInStorage .setSignInStatus (anyBoolean ())).thenReturn (Tasks .forResult (null ));
201
+ setSignInStatusSharedPreference (true );
198
202
199
203
when (mockInstallationTokenResult .getToken ()).thenReturn (TEST_AUTH_TOKEN );
200
204
@@ -244,7 +248,7 @@ public void checkForNewRelease_whenCheckForNewReleaseFails_throwsError() {
244
248
245
249
@ Test
246
250
public void checkForNewRelease_testerIsNotSignedIn_taskFails () {
247
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
251
+ setSignInStatusSharedPreference ( false );
248
252
249
253
Task <AppDistributionRelease > task = firebaseAppDistribution .checkForNewRelease ();
250
254
@@ -277,12 +281,12 @@ public void checkForNewRelease_authenticationFailure_signOutTester() throws Inte
277
281
278
282
awaitTaskFailure (task , AUTHENTICATION_FAILURE , "Test" );
279
283
awaitTermination (lightweightExecutor );
280
- verify (mockSignInStorage , times (1 )).setSignInStatus (false );
284
+ verify (signInStorage , times (1 )).setSignInStatus (false );
281
285
}
282
286
283
287
@ Test
284
288
public void updateApp_whenNotSignedIn_throwsError () {
285
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
289
+ setSignInStatusSharedPreference ( false );
286
290
287
291
UpdateTask updateTask = firebaseAppDistribution .updateApp ();
288
292
@@ -372,7 +376,7 @@ public void updateIfNewReleaseAvailable_whenActivityBackgrounded_updateDialogNot
372
376
@ Test
373
377
public void updateIfNewReleaseAvailable_whenSignInCancelled_checkForUpdateNotCalled ()
374
378
throws InterruptedException {
375
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
379
+ setSignInStatusSharedPreference ( false );
376
380
when (mockTesterSignInManager .signInTester ())
377
381
.thenReturn (
378
382
Tasks .forException (
@@ -393,7 +397,7 @@ public void updateIfNewReleaseAvailable_whenSignInCancelled_checkForUpdateNotCal
393
397
@ Test
394
398
public void updateIfNewReleaseAvailable_whenSignInFailed_checkForUpdateNotCalled ()
395
399
throws InterruptedException {
396
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
400
+ setSignInStatusSharedPreference ( false );
397
401
when (mockTesterSignInManager .signInTester ())
398
402
.thenReturn (
399
403
Tasks .forException (
@@ -469,7 +473,6 @@ public void updateIfNewReleaseAvailable_whenCheckForUpdateFails_updateAppNotCall
469
473
public void updateIfNewReleaseAvailable_whenTesterIsSignedIn_doesNotOpenDialog ()
470
474
throws InterruptedException , FirebaseAppDistributionException , ExecutionException {
471
475
when (mockNewReleaseFetcher .checkForNewRelease ()).thenReturn (Tasks .forResult (null ));
472
- when (mockSignInStorage .getSignInStatus ()).thenReturn (Tasks .forResult (true ));
473
476
474
477
UpdateTask task = firebaseAppDistribution .updateIfNewReleaseAvailable ();
475
478
awaitTask (task );
@@ -479,8 +482,8 @@ public void updateIfNewReleaseAvailable_whenTesterIsSignedIn_doesNotOpenDialog()
479
482
480
483
@ Test
481
484
public void signInTester_whenDialogDismissed_taskFails () throws InterruptedException {
482
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
483
- Task updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
485
+ setSignInStatusSharedPreference ( false );
486
+ UpdateTask updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
484
487
awaitAsyncOperations (lightweightExecutor );
485
488
486
489
AlertDialog dialog = assertAlertDialogShown ();
@@ -492,8 +495,8 @@ public void signInTester_whenDialogDismissed_taskFails() throws InterruptedExcep
492
495
@ Test
493
496
public void updateIfNewReleaseAvailable_whenSignInDialogCanceled_taskFails ()
494
497
throws InterruptedException {
495
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
496
- Task signInTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
498
+ setSignInStatusSharedPreference ( false );
499
+ UpdateTask signInTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
497
500
awaitAsyncOperations (lightweightExecutor );
498
501
499
502
AlertDialog dialog = assertAlertDialogShown ();
@@ -514,7 +517,7 @@ private AlertDialog assertAlertDialogShown() {
514
517
public void signOutTester_setsSignInStatusFalse () {
515
518
firebaseAppDistribution .signOutTester ();
516
519
517
- verify ( mockSignInStorage ). setSignInStatus ( false );
520
+ assertThat ( signInStorage . getSignInStatusBlocking ()). isFalse ( );
518
521
}
519
522
520
523
@ Test
@@ -532,6 +535,30 @@ public void signOutTester_unsetsCachedNewRelease()
532
535
assertThat (cachedNewReleaseTask .getResult ()).isNull ();
533
536
}
534
537
538
+ @ Test
539
+ public void isTesterSignedIn_returnsTrueWhenSharePreferenceIsTrue () {
540
+ setSignInStatusSharedPreference (true );
541
+ assertThat (firebaseAppDistribution .isTesterSignedIn ()).isTrue ();
542
+ }
543
+
544
+ @ Test
545
+ public void isTesterSignedIn_returnsFalseWhenSharePreferenceIsFalse () {
546
+ setSignInStatusSharedPreference (false );
547
+ assertThat (firebaseAppDistribution .isTesterSignedIn ()).isFalse ();
548
+ }
549
+
550
+ @ Test
551
+ public void isTesterSignedIn_whenStorageWarmedUp_returnsCorrectStatusImmediately () {
552
+ // First check the sign in status, which has the side effect of warming up the SharedPreferences
553
+ // instance. This simulates a typical flow, where a developer would check the status before
554
+ // trying to sign out the tester.
555
+ firebaseAppDistribution .isTesterSignedIn ();
556
+
557
+ firebaseAppDistribution .signOutTester ();
558
+
559
+ assertThat (firebaseAppDistribution .isTesterSignedIn ()).isFalse ();
560
+ }
561
+
535
562
@ Test
536
563
public void updateIfNewReleaseAvailable_receiveProgressUpdateFromUpdateApp ()
537
564
throws InterruptedException {
@@ -565,21 +592,21 @@ public void updateIfNewReleaseAvailable_receiveProgressUpdateFromUpdateApp()
565
592
@ Test
566
593
public void updateIfNewReleaseAvailable_fromABackgroundThread_showsSignInDialog ()
567
594
throws InterruptedException , ExecutionException {
568
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
595
+ setSignInStatusSharedPreference ( false );
569
596
570
597
ExecutorService executorService = Executors .newSingleThreadExecutor ();
571
598
Future <UpdateTask > future =
572
599
executorService .submit (() -> firebaseAppDistribution .updateIfNewReleaseAvailable ());
573
600
awaitAsyncOperations (executorService );
574
601
575
602
assertAlertDialogShown ();
576
- assertFalse ((( UpdateTask ) future .get ()).isComplete ());
603
+ assertFalse ((future .get ()).isComplete ());
577
604
}
578
605
579
606
@ Test
580
607
public void updateIfNewReleaseAvailable_whenScreenRotates_signInConfirmationDialogReappears ()
581
608
throws InterruptedException {
582
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
609
+ setSignInStatusSharedPreference ( false );
583
610
when (activity .isChangingConfigurations ()).thenReturn (true );
584
611
585
612
UpdateTask updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
@@ -597,8 +624,8 @@ public void updateIfNewReleaseAvailable_whenScreenRotates_signInConfirmationDial
597
624
@ Test
598
625
public void updateIfNewReleaseAvailable_whenScreenRotates_updateDialogReappears ()
599
626
throws InterruptedException {
600
- AppDistributionReleaseInternal newRelease = TEST_RELEASE_NEWER_AAB_INTERNAL ;
601
- when ( mockNewReleaseFetcher . checkForNewRelease ()). thenReturn (Tasks .forResult (newRelease ));
627
+ when ( mockNewReleaseFetcher . checkForNewRelease ())
628
+ . thenReturn (Tasks .forResult (TEST_RELEASE_NEWER_AAB_INTERNAL ));
602
629
when (activity .isChangingConfigurations ()).thenReturn (true );
603
630
604
631
UpdateTask updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
@@ -617,7 +644,7 @@ public void updateIfNewReleaseAvailable_whenScreenRotates_updateDialogReappears(
617
644
updateIfNewReleaseAvailable_whenSignInDialogShowingAndNewActivityStarts_signInTaskCancelled ()
618
645
throws InterruptedException {
619
646
TestActivity testActivity2 = new TestActivity ();
620
- when ( mockSignInStorage . getSignInStatus ()). thenReturn ( Tasks . forResult ( false ) );
647
+ setSignInStatusSharedPreference ( false );
621
648
622
649
UpdateTask updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
623
650
awaitAsyncOperations (lightweightExecutor );
@@ -635,8 +662,8 @@ public void updateIfNewReleaseAvailable_whenScreenRotates_updateDialogReappears(
635
662
updateIfNewReleaseAvailable_whenUpdateDialogShowingAndNewActivityStarts_updateTaskCancelled ()
636
663
throws InterruptedException {
637
664
TestActivity testActivity2 = new TestActivity ();
638
- AppDistributionReleaseInternal newRelease = TEST_RELEASE_NEWER_AAB_INTERNAL ;
639
- when ( mockNewReleaseFetcher . checkForNewRelease ()). thenReturn (Tasks .forResult (newRelease ));
665
+ when ( mockNewReleaseFetcher . checkForNewRelease ())
666
+ . thenReturn (Tasks .forResult (TEST_RELEASE_NEWER_AAB_INTERNAL ));
640
667
641
668
UpdateTask updateTask = firebaseAppDistribution .updateIfNewReleaseAvailable ();
642
669
awaitAsyncOperations (lightweightExecutor );
@@ -652,7 +679,6 @@ public void updateIfNewReleaseAvailable_whenScreenRotates_updateDialogReappears(
652
679
@ Test
653
680
public void updateAppTask_whenNoReleaseAvailable_throwsError () {
654
681
firebaseAppDistribution .getCachedNewRelease ().set (null );
655
- when (mockSignInStorage .getSignInStatus ()).thenReturn (Tasks .forResult (true ));
656
682
657
683
UpdateTask updateTask = firebaseAppDistribution .updateApp ();
658
684
@@ -666,7 +692,6 @@ public void updateApp_withAabReleaseAvailable_returnsSameAabTask()
666
692
firebaseAppDistribution .getCachedNewRelease ().set (release );
667
693
UpdateTaskImpl updateTaskToReturn = new UpdateTaskImpl ();
668
694
doReturn (updateTaskToReturn ).when (mockAabUpdater ).updateAab (release );
669
- when (mockSignInStorage .getSignInStatus ()).thenReturn (Tasks .forResult (true ));
670
695
671
696
UpdateTask updateTask = firebaseAppDistribution .updateApp ();
672
697
assertFalse (updateTask .isComplete ());
@@ -682,7 +707,6 @@ public void updateApp_withAabReleaseAvailable_returnsSameAabTask()
682
707
@ Test
683
708
public void updateApp_withApkReleaseAvailable_returnsSameApkTask ()
684
709
throws InterruptedException , FirebaseAppDistributionException , ExecutionException {
685
- when (mockSignInStorage .getSignInStatus ()).thenReturn (Tasks .forResult (true ));
686
710
AppDistributionReleaseInternal release = TEST_RELEASE_NEWER_APK_INTERNAL ;
687
711
firebaseAppDistribution .getCachedNewRelease ().set (release );
688
712
UpdateTaskImpl updateTaskToReturn = new UpdateTaskImpl ();
@@ -829,9 +853,16 @@ private static void assertLoggedError(String partialMessage, Throwable e) {
829
853
log ->
830
854
log .type == Log .ERROR
831
855
&& log .msg .contains (partialMessage )
832
- && (e != null ? log .throwable == e : true );
856
+ && (e == null || log .throwable == e );
833
857
List <ShadowLog .LogItem > matchingLogs =
834
858
ShadowLog .getLogs ().stream ().filter (predicate ).collect (toList ());
835
859
assertThat (matchingLogs ).hasSize (1 );
836
860
}
861
+
862
+ private void setSignInStatusSharedPreference (boolean testerSignedIn ) {
863
+ SharedPreferences sharedPreferences =
864
+ ApplicationProvider .getApplicationContext ()
865
+ .getSharedPreferences (SignInStorage .SIGNIN_PREFERENCES_NAME , MODE_PRIVATE );
866
+ sharedPreferences .edit ().putBoolean (SignInStorage .SIGNIN_TAG , testerSignedIn ).commit ();
867
+ }
837
868
}
0 commit comments