Skip to content

Commit e81db5b

Browse files
authored
Create GIDFakeAuthStateMigration (#529)
1 parent 0b30eb6 commit e81db5b

File tree

8 files changed

+125
-19
lines changed

8 files changed

+125
-19
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h"
18+
19+
/// A fake |GIDAuthStateMigration| for testing.
20+
@interface GIDFakeAuthStateMigration : GIDAuthStateMigration
21+
22+
/// Callback that is called when `migrateIfNeededWithTokenURL` is invoked.
23+
@property (nonatomic, nullable) void (^migrationInvokedCallback)
24+
(NSURL * _Nullable tokenURL, NSString * _Nullable callbackPath, NSString * _Nullable keychainName,
25+
BOOL isFreshInstall);
26+
27+
@end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h"
18+
19+
NS_ASSUME_NONNULL_BEGIN
20+
21+
@implementation GIDFakeAuthStateMigration
22+
23+
@synthesize migrationInvokedCallback = _migrationInvokedCallback;
24+
25+
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore {
26+
self = [super initWithKeychainStore:keychainStore];
27+
return self;
28+
}
29+
30+
- (void)migrateIfNeededWithTokenURL:(NSURL *)tokenURL
31+
callbackPath:(NSString *)callbackPath
32+
keychainName:(NSString *)keychainName
33+
isFreshInstall:(BOOL)isFreshInstall {
34+
if (_migrationInvokedCallback) {
35+
_migrationInvokedCallback(tokenURL, callbackPath, keychainName, isFreshInstall);
36+
}
37+
return;
38+
}
39+
40+
@end
41+
42+
NS_ASSUME_NONNULL_END

GoogleSignIn/Sources/GIDAuthStateMigration.h renamed to GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h

File renamed without changes.

GoogleSignIn/Sources/GIDAuthStateMigration.m renamed to GoogleSignIn/Sources/GIDAuthStateMigration/Implementation/GIDAuthStateMigration.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#import "GoogleSignIn/Sources/GIDAuthStateMigration.h"
16-
15+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h"
1716
#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
1817

1918
@import GTMAppAuth;

GoogleSignIn/Sources/GIDSignIn.m

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h"
2222
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignInResult.h"
2323

24-
#import "GoogleSignIn/Sources/GIDAuthStateMigration.h"
24+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h"
2525
#import "GoogleSignIn/Sources/GIDEMMSupport.h"
2626
#import "GoogleSignIn/Sources/GIDSignInInternalOptions.h"
2727
#import "GoogleSignIn/Sources/GIDSignInPreferences.h"
@@ -490,15 +490,19 @@ + (GIDSignIn *)sharedInstance {
490490
dispatch_once(&once, ^{
491491
GTMKeychainStore *keychainStore =
492492
[[GTMKeychainStore alloc] initWithItemName:kGTMAppAuthKeychainName];
493+
GIDAuthStateMigration *authStateMigrationService =
494+
[[GIDAuthStateMigration alloc] initWithKeychainStore:keychainStore];
493495
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
494496
if (@available(iOS 14.0, *)) {
495497
GIDAppCheck *appCheck = [GIDAppCheck appCheckUsingAppAttestProvider];
496498
sharedInstance = [[self alloc] initWithKeychainStore:keychainStore
499+
authStateMigrationService:authStateMigrationService
497500
appCheck:appCheck];
498501
}
499502
#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST
500503
if (!sharedInstance) {
501-
sharedInstance = [[self alloc] initWithKeychainStore:keychainStore];
504+
sharedInstance = [[self alloc] initWithKeychainStore:keychainStore
505+
authStateMigrationService:authStateMigrationService];
502506
}
503507
});
504508
return sharedInstance;
@@ -533,7 +537,8 @@ - (void)configureDebugProviderWithAPIKey:(NSString *)APIKey
533537

534538
#pragma mark - Private methods
535539

536-
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore {
540+
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore
541+
authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService {
537542
self = [super init];
538543
if (self) {
539544
// Get the bundle of the current executable.
@@ -561,20 +566,20 @@ - (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore {
561566
tokenEndpoint:[NSURL URLWithString:tokenEndpointURL]];
562567
_keychainStore = keychainStore;
563568
// Perform migration of auth state from old versions of the SDK if needed.
564-
GIDAuthStateMigration *migration =
565-
[[GIDAuthStateMigration alloc] initWithKeychainStore:_keychainStore];
566-
[migration migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint
567-
callbackPath:kBrowserCallbackPath
568-
keychainName:kGTMAppAuthKeychainName
569-
isFreshInstall:isFreshInstall];
569+
[authStateMigrationService migrateIfNeededWithTokenURL:_appAuthConfiguration.tokenEndpoint
570+
callbackPath:kBrowserCallbackPath
571+
keychainName:kGTMAppAuthKeychainName
572+
isFreshInstall:isFreshInstall];
570573
}
571574
return self;
572575
}
573576

574577
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
575578
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore
579+
authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService
576580
appCheck:(GIDAppCheck *)appCheck {
577-
self = [self initWithKeychainStore:keychainStore];
581+
self = [self initWithKeychainStore:keychainStore
582+
authStateMigrationService:authStateMigrationService];
578583
if (self) {
579584
_appCheck = appCheck;
580585
_configureAppCheckCalled = NO;

GoogleSignIn/Sources/GIDSignIn_Private.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
3030
@class GIDSignInInternalOptions;
3131
@class GTMKeychainStore;
3232
@class GIDAppCheck;
33+
@class GIDAuthStateMigration;
3334

3435
/// Represents a completion block that takes a `GIDSignInResult` on success or an error if the
3536
/// operation was unsuccessful.
@@ -46,11 +47,13 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
4647
@property(nonatomic, readwrite, nullable) GIDGoogleUser *currentUser;
4748

4849
/// Private initializer taking a `GTMKeychainStore`.
49-
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore;
50+
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore
51+
authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService;
5052

5153
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
5254
/// Private initializer taking a `GTMKeychainStore` and `GIDAppCheckProvider`.
5355
- (instancetype)initWithKeychainStore:(GTMKeychainStore *)keychainStore
56+
authStateMigrationService:(GIDAuthStateMigration *)authStateMigrationService
5457
appCheck:(GIDAppCheck *)appCheck
5558
API_AVAILABLE(ios(14));
5659
#endif // TARGET_OS_IOS || !TARGET_OS_MACCATALYST

GoogleSignIn/Tests/Unit/GIDAuthStateMigrationTest.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#import <XCTest/XCTest.h>
1616

17-
#import "GoogleSignIn/Sources/GIDAuthStateMigration.h"
17+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/GIDAuthStateMigration.h"
1818
#import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
1919
#if TARGET_OS_OSX
2020
#import "GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h"

GoogleSignIn/Tests/Unit/GIDSignInTest.m

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#import "GoogleSignIn/Sources/GIDEMMErrorHandler.h"
4141
#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST
4242

43+
#import "GoogleSignIn/Sources/GIDAuthStateMigration/Fake/GIDFakeAuthStateMigration.h"
4344
#import "GoogleSignIn/Tests/Unit/GIDFakeFetcher.h"
4445
#import "GoogleSignIn/Tests/Unit/GIDFakeFetcherService.h"
4546
#import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h"
@@ -221,6 +222,9 @@ @interface GIDSignInTest : XCTestCase {
221222
// Whether callback block has been called.
222223
BOOL _completionCalled;
223224

225+
// Fake for |GIDAuthStateMigration|.
226+
GIDFakeAuthStateMigration *_authStateMigrationService;
227+
224228
// Fake fetcher service to emulate network requests.
225229
GIDFakeFetcherService *_fetcherService;
226230

@@ -331,6 +335,7 @@ - (void)setUp {
331335
callback:COPY_TO_ARG_BLOCK(self->_savedTokenCallback)]);
332336

333337
// Fakes
338+
_authStateMigrationService = [[GIDFakeAuthStateMigration alloc] init];
334339
_fetcherService = [[GIDFakeFetcherService alloc] init];
335340
_fakeMainBundle = [[GIDFakeMainBundle alloc] init];
336341
[_fakeMainBundle startFakingWithClientID:kClientId];
@@ -339,7 +344,8 @@ - (void)setUp {
339344
// Object under test
340345
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAppHasRunBeforeKey];
341346

342-
_signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore];
347+
_signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore
348+
authStateMigrationService:_authStateMigrationService];
343349
_hint = nil;
344350

345351
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
@@ -398,6 +404,7 @@ - (void)testConfigureSucceeds {
398404
userDefaults:_testUserDefaults];
399405

400406
GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore
407+
authStateMigrationService:_authStateMigrationService
401408
appCheck:appCheck];
402409
[signIn configureWithCompletion:^(NSError * _Nullable error) {
403410
XCTAssertNil(error);
@@ -421,6 +428,7 @@ - (void)testConfigureFailsNoTokenOrError {
421428
userDefaults:_testUserDefaults];
422429

423430
GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:_keychainStore
431+
authStateMigrationService:_authStateMigrationService
424432
appCheck:appCheck];
425433

426434
// Should fail if missing both token and error
@@ -439,7 +447,8 @@ - (void)testConfigureFailsNoTokenOrError {
439447
- (void)testInitWithKeychainStore {
440448
GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"];
441449
GIDSignIn *signIn;
442-
signIn = [[GIDSignIn alloc] initWithKeychainStore:store];
450+
signIn = [[GIDSignIn alloc] initWithKeychainStore:store
451+
authStateMigrationService:_authStateMigrationService];
443452
XCTAssertNotNil(signIn.configuration);
444453
XCTAssertEqual(signIn.configuration.clientID, kClientId);
445454
XCTAssertNil(signIn.configuration.serverClientID);
@@ -454,7 +463,8 @@ - (void)testInitWithKeychainStore_noConfig {
454463
openIDRealm:nil];
455464
GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"];
456465
GIDSignIn *signIn;
457-
signIn = [[GIDSignIn alloc] initWithKeychainStore:store];
466+
signIn = [[GIDSignIn alloc] initWithKeychainStore:store
467+
authStateMigrationService:_authStateMigrationService];
458468
XCTAssertNil(signIn.configuration);
459469
}
460470

@@ -466,7 +476,8 @@ - (void)testInitWithKeychainStore_fullConfig {
466476

467477
GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"];
468478
GIDSignIn *signIn;
469-
signIn = [[GIDSignIn alloc] initWithKeychainStore:store];
479+
signIn = [[GIDSignIn alloc] initWithKeychainStore:store
480+
authStateMigrationService:_authStateMigrationService];
470481
XCTAssertNotNil(signIn.configuration);
471482
XCTAssertEqual(signIn.configuration.clientID, kClientId);
472483
XCTAssertEqual(signIn.configuration.serverClientID, kServerClientId);
@@ -481,10 +492,29 @@ - (void)testInitWithKeychainStore_invalidConfig {
481492
openIDRealm:nil];
482493
GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:@"foo"];
483494
GIDSignIn *signIn;
484-
signIn = [[GIDSignIn alloc] initWithKeychainStore:store];
495+
signIn = [[GIDSignIn alloc] initWithKeychainStore:store
496+
authStateMigrationService:_authStateMigrationService];
485497
XCTAssertNil(signIn.configuration);
486498
}
487499

500+
- (void)testInitWithKeychainStore_attemptsMigration {
501+
NSString *expectedKeychainName = @"foo";
502+
503+
XCTestExpectation *expectation = [self expectationWithDescription:@"Callback should be called."];
504+
_authStateMigrationService.migrationInvokedCallback =
505+
^(NSURL *tokenURL, NSString *callbackPath, NSString *keychainName, BOOL isFreshInstall) {
506+
XCTAssertFalse(isFreshInstall);
507+
[expectation fulfill];
508+
};
509+
510+
GTMKeychainStore *store = [[GTMKeychainStore alloc] initWithItemName:expectedKeychainName];
511+
GIDSignIn *signIn = [[GIDSignIn alloc] initWithKeychainStore:store
512+
authStateMigrationService:_authStateMigrationService];
513+
514+
XCTAssertNotNil(signIn.configuration);
515+
[self waitForExpectationsWithTimeout:1 handler:nil];
516+
}
517+
488518
- (void)testRestorePreviousSignInNoRefresh_hasPreviousUser {
489519
[[[_authorization stub] andReturn:_authState] authState];
490520
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST

0 commit comments

Comments
 (0)