From 30699dff05984dfc4d5f710c6d151f5c3a86a707 Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 19 Sep 2022 17:55:05 -0700 Subject: [PATCH 1/9] Add KVO in GIDGoogleUser Send KVO notifications when authState updates tokens. --- GoogleSignIn/Sources/GIDGoogleUser.m | 57 +++++++++++++++------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index b03bd55d..6e0242c4 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -102,36 +102,14 @@ - (GIDConfiguration *)configuration { } - (GIDToken *)accessToken { - @synchronized(self) { - if (!_cachedAccessToken) { - _cachedAccessToken = [[GIDToken alloc] initWithTokenString:_authState.lastTokenResponse.accessToken - expirationDate:_authState.lastTokenResponse. - accessTokenExpirationDate]; - } - } return _cachedAccessToken; } - (GIDToken *)refreshToken { - @synchronized(self) { - if (!_cachedRefreshToken) { - _cachedRefreshToken = [[GIDToken alloc] initWithTokenString:_authState.refreshToken - expirationDate:nil]; - } - } return _cachedRefreshToken; } - (nullable GIDToken *)idToken { - @synchronized(self) { - NSString *idTokenString = _authState.lastTokenResponse.idToken; - if (!_cachedIdToken && idTokenString) { - NSDate *idTokenExpirationDate = [[[OIDIDToken alloc] - initWithIDTokenString:idTokenString] expiresAt]; - _cachedIdToken = [[GIDToken alloc] initWithTokenString:idTokenString - expirationDate:idTokenExpirationDate]; - } - } return _cachedIdToken; } @@ -153,10 +131,25 @@ - (void)updateAuthState:(OIDAuthState *)authState _authentication = [[GIDAuthentication alloc] initWithAuthState:authState]; _profile = profileData; - // These three tokens will be generated in the getter and cached . - _cachedAccessToken = nil; - _cachedRefreshToken = nil; - _cachedIdToken = nil; + [self sendKVONotificationsBeforeChanges]; + [self updateTokensWithAuthState:authState]; + [self sendKVONotificationAfterChanges]; + } +} + +- (void)updateTokensWithAuthState:(OIDAuthState *)authState { + _cachedAccessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken + expirationDate:authState.lastTokenResponse. + accessTokenExpirationDate]; + _cachedRefreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken + expirationDate:nil]; + _cachedIdToken = nil; + NSString *idTokenString = authState.lastTokenResponse.idToken; + if (idTokenString) { + NSDate *idTokenExpirationDate = [[[OIDIDToken alloc] + initWithIDTokenString:idTokenString] expiresAt]; + _cachedIdToken = [[GIDToken alloc] initWithTokenString:idTokenString + expirationDate:idTokenExpirationDate]; } } @@ -173,6 +166,18 @@ - (nullable NSString *)hostedDomain { return nil; } +- (void)sendKVONotificationsBeforeChanges { + [self willChangeValueForKey:NSStringFromSelector(@selector(accessToken))]; + [self willChangeValueForKey:NSStringFromSelector(@selector(refreshToken))]; + [self willChangeValueForKey:NSStringFromSelector(@selector(idToken))]; +} + +- (void)sendKVONotificationAfterChanges { + [self didChangeValueForKey:NSStringFromSelector(@selector(accessToken))]; + [self didChangeValueForKey:NSStringFromSelector(@selector(refreshToken))]; + [self didChangeValueForKey:NSStringFromSelector(@selector(idToken))]; +} + #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { From 9ac54783eb4f3c2daa67b4e3dbe0aeb84ce931f7 Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 19 Sep 2022 18:14:36 -0700 Subject: [PATCH 2/9] Observe KVO in GIDGoogleUserTest Uses bit mask to verify KVO notifications are sent. --- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 105 ++++++++++++++++++-- 1 file changed, 98 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 2ff9e567..9b2e5ddc 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -41,10 +41,45 @@ // It should be larger than kTimeAccuracy which is used in the method `XCTAssertEqualWithAccuracy`. static NSTimeInterval const kTimeIncrement = 100; +// List of observed properties of the class being tested. +static NSString *const kObservedProperties[] = { + @"accessToken", + @"refreshToken", + @"idToken", +}; +static const NSUInteger kNumberOfObservedProperties = + sizeof(kObservedProperties) / sizeof(*kObservedProperties); + +// Bit position for notification change type bitmask flags. +// Must match the list of observed properties above. +typedef NS_ENUM(NSUInteger, ChangeType) { + kChangeTypeAccessTokenPrior, + kChangeTypeAccessToken, + kChangeTypeRefreshTokenPrior, + kChangeTypeRefreshToken, + kChangeTypeIDTokenPrior, + kChangeTypeIDToken, + kChangeTypeEnd // not a real change type but an end mark for calculating |kChangeAll| +}; + +static const NSUInteger kChangeAll = (1u << kChangeTypeEnd) - 1u; + +#if __has_feature(c_static_assert) || __has_extension(c_static_assert) +_Static_assert(kChangeTypeEnd == (sizeof(kObservedProperties) / sizeof(*kObservedProperties)) * 2, + "List of observed properties must match list of change notification enums"); +#endif + @interface GIDGoogleUserTest : XCTestCase @end -@implementation GIDGoogleUserTest +@implementation GIDGoogleUserTest { + // Bitmask flags for observed changes, as specified in |ChangeType|. + NSUInteger _changesObserved; +} + +- (void)setUp { + _changesObserved = 0; +} #pragma mark - Tests @@ -102,12 +137,8 @@ - (void)testUpdateAuthState { NSTimeInterval accessTokenExpireTime = [NSDate timeIntervalSinceReferenceDate]; NSTimeInterval idTokenExpireTime = accessTokenExpireTime + kTimeIncrement; - NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; - OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken - accessToken:kAccessToken - accessTokenExpireTime:accessTokenExpireTime]; - - GIDGoogleUser *user = [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; + GIDGoogleUser *user = [self observedGoogleUserWithAccessTokenExpireTime:accessTokenExpireTime + idTokenExpireTime:idTokenExpireTime]; NSTimeInterval updatedAccessTokenExpireTime = idTokenExpireTime + kTimeIncrement; NSTimeInterval updatedIDTokenExpireTime = updatedAccessTokenExpireTime + kTimeIncrement; @@ -126,12 +157,72 @@ - (void)testUpdateAuthState { XCTAssertEqualWithAccuracy([user.idToken.expirationDate timeIntervalSinceReferenceDate], updatedIDTokenExpireTime, kTimeAccuracy); XCTAssertEqual(user.profile, updatedProfileData); + XCTAssertEqual(_changesObserved, kChangeAll); } #pragma mark - Helpers +- (GIDGoogleUser *)observedGoogleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { + GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime + idTokenExpireTime:idTokenExpireTime]; + for (unsigned int i = 0; i < kNumberOfObservedProperties; ++i) { + [user addObserver:self + forKeyPath:kObservedProperties[i] + options:NSKeyValueObservingOptionPrior + context:NULL]; + } + return user; +} + +- (GIDGoogleUser *)googleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { + + NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; + OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken + accessToken:kAccessToken + accessTokenExpireTime:accessTokenExpireTime]; + + return [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; +} + - (NSString *)idTokenWithExpireTime:(NSTimeInterval)expireTime { return [OIDTokenResponse idTokenWithSub:kUserID exp:@(expireTime + NSTimeIntervalSince1970)]; } +#pragma mark - NSKeyValueObserving + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + ChangeType changeType; + if ([keyPath isEqualToString:@"accessToken"]) { + if (change[NSKeyValueChangeNotificationIsPriorKey]) { + changeType = kChangeTypeAccessTokenPrior; + } else { + changeType = kChangeTypeAccessToken; + } + } else if ([keyPath isEqualToString:@"refreshToken"]) { + if (change[NSKeyValueChangeNotificationIsPriorKey]) { + changeType = kChangeTypeRefreshTokenPrior; + } else { + changeType = kChangeTypeRefreshToken; + } + } else if ([keyPath isEqualToString:@"idToken"]) { + if (change[NSKeyValueChangeNotificationIsPriorKey]) { + changeType = kChangeTypeIDTokenPrior; + } else { + changeType = kChangeTypeIDToken; + } + } else { + XCTFail(@"unexpected keyPath"); + return; // so compiler knows |changeType| is always assigned + } + + NSInteger changeMask = 1 << changeType; + XCTAssertFalse(_changesObserved & changeMask); // each change type should only fire once + _changesObserved |= changeMask; +} + @end From 26784fe5ac207be94d4f9b71ebdc476f9bb49bad Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 22 Sep 2022 11:07:26 -0700 Subject: [PATCH 3/9] Utilize the class extension and automatic KVO notifications --- GoogleSignIn/Sources/GIDGoogleUser.m | 58 ++++++++++------------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 6e0242c4..7e394441 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -42,12 +42,19 @@ NS_ASSUME_NONNULL_BEGIN +@interface GIDGoogleUser() + +@property(nonatomic, readwrite) GIDToken *accessToken; + +@property(nonatomic, readwrite) GIDToken *refreshToken; + +@property(nonatomic, readwrite, nullable) GIDToken *idToken; + +@end + @implementation GIDGoogleUser { OIDAuthState *_authState; GIDConfiguration *_cachedConfiguration; - GIDToken *_cachedAccessToken; - GIDToken *_cachedRefreshToken; - GIDToken *_cachedIdToken; } - (nullable NSString *)userID { @@ -59,7 +66,6 @@ - (nullable NSString *)userID { return [idTokenDecoded.subject copy]; } } - return nil; } @@ -97,22 +103,9 @@ - (GIDConfiguration *)configuration { openIDRealm:openIDRealm]; }; } - return _cachedConfiguration; } -- (GIDToken *)accessToken { - return _cachedAccessToken; -} - -- (GIDToken *)refreshToken { - return _cachedRefreshToken; -} - -- (nullable GIDToken *)idToken { - return _cachedIdToken; -} - #pragma mark - Private Methods - (instancetype)initWithAuthState:(OIDAuthState *)authState @@ -131,25 +124,26 @@ - (void)updateAuthState:(OIDAuthState *)authState _authentication = [[GIDAuthentication alloc] initWithAuthState:authState]; _profile = profileData; - [self sendKVONotificationsBeforeChanges]; [self updateTokensWithAuthState:authState]; - [self sendKVONotificationAfterChanges]; } } - (void)updateTokensWithAuthState:(OIDAuthState *)authState { - _cachedAccessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken - expirationDate:authState.lastTokenResponse. - accessTokenExpirationDate]; - _cachedRefreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken - expirationDate:nil]; - _cachedIdToken = nil; + self.accessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken + expirationDate:authState.lastTokenResponse. + accessTokenExpirationDate]; + + self.refreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken + expirationDate:nil]; + NSString *idTokenString = authState.lastTokenResponse.idToken; if (idTokenString) { NSDate *idTokenExpirationDate = [[[OIDIDToken alloc] initWithIDTokenString:idTokenString] expiresAt]; - _cachedIdToken = [[GIDToken alloc] initWithTokenString:idTokenString + self.idToken = [[GIDToken alloc] initWithTokenString:idTokenString expirationDate:idTokenExpirationDate]; + } else { + self.idToken = nil; } } @@ -166,18 +160,6 @@ - (nullable NSString *)hostedDomain { return nil; } -- (void)sendKVONotificationsBeforeChanges { - [self willChangeValueForKey:NSStringFromSelector(@selector(accessToken))]; - [self willChangeValueForKey:NSStringFromSelector(@selector(refreshToken))]; - [self willChangeValueForKey:NSStringFromSelector(@selector(idToken))]; -} - -- (void)sendKVONotificationAfterChanges { - [self didChangeValueForKey:NSStringFromSelector(@selector(accessToken))]; - [self didChangeValueForKey:NSStringFromSelector(@selector(refreshToken))]; - [self didChangeValueForKey:NSStringFromSelector(@selector(idToken))]; -} - #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { From 6e5d21adfa5e29158a387aed0b6c31e4fdfb0ae1 Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 22 Sep 2022 13:36:03 -0700 Subject: [PATCH 4/9] Only update tokens if necessary --- GoogleSignIn/Sources/GIDGoogleUser.m | 20 ++++++++++++++----- .../Tests/Unit/GIDAuthenticationTest.m | 2 ++ GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 9 +++++++-- GoogleSignIn/Tests/Unit/GIDSignInTest.m | 1 + .../Tests/Unit/OIDAuthState+Testing.h | 3 ++- .../Tests/Unit/OIDAuthState+Testing.m | 4 +++- .../Tests/Unit/OIDTokenResponse+Testing.h | 1 + .../Tests/Unit/OIDTokenResponse+Testing.m | 4 +++- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 7e394441..979a164f 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface GIDGoogleUser() +@interface GIDGoogleUser () @property(nonatomic, readwrite) GIDToken *accessToken; @@ -129,21 +129,31 @@ - (void)updateAuthState:(OIDAuthState *)authState } - (void)updateTokensWithAuthState:(OIDAuthState *)authState { - self.accessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken + GIDToken *accessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken expirationDate:authState.lastTokenResponse. accessTokenExpirationDate]; + if (![self.accessToken isEqualToToken:accessToken]) { + self.accessToken = accessToken; + } - self.refreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken + GIDToken *refreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken expirationDate:nil]; + if (![self.refreshToken isEqualToToken:refreshToken]) { + self.refreshToken = refreshToken; + } + GIDToken *idToken; NSString *idTokenString = authState.lastTokenResponse.idToken; if (idTokenString) { NSDate *idTokenExpirationDate = [[[OIDIDToken alloc] initWithIDTokenString:idTokenString] expiresAt]; - self.idToken = [[GIDToken alloc] initWithTokenString:idTokenString + idToken = [[GIDToken alloc] initWithTokenString:idTokenString expirationDate:idTokenExpirationDate]; } else { - self.idToken = nil; + idToken = nil; + } + if ((self.idToken || idToken) && ![self.idToken isEqualToToken:idToken]) { + self.idToken = idToken; } } diff --git a/GoogleSignIn/Tests/Unit/GIDAuthenticationTest.m b/GoogleSignIn/Tests/Unit/GIDAuthenticationTest.m index ad57bead..769d3235 100644 --- a/GoogleSignIn/Tests/Unit/GIDAuthenticationTest.m +++ b/GoogleSignIn/Tests/Unit/GIDAuthenticationTest.m @@ -561,6 +561,7 @@ - (GIDAuthentication *)auth { [OIDTokenResponse testInstanceWithIDToken:idToken accessToken:kAccessToken expiresIn:accessTokenExpiresIn + refreshToken:kRefreshToken tokenRequest:tokenRequest]; return [[GIDAuthentication alloc] initWithAuthState:[OIDAuthState testInstanceWithTokenResponse:tokenResponse]]; @@ -599,6 +600,7 @@ - (OIDTokenResponse *)tokenResponseWithNewTokens { return [OIDTokenResponse testInstanceWithIDToken:(_hasIDToken ? [self idTokenNew] : nil) accessToken:kNewAccessToken expiresIn:expiresIn + refreshToken:kRefreshToken tokenRequest:_tokenRequest ?: nil]; } diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 9b2e5ddc..56e0815b 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -36,6 +36,8 @@ #endif static NSString *const kNewAccessToken = @"new_access_token"; +static NSString *const kNewRefreshToken = @"new_refresh_token"; + static NSTimeInterval const kTimeAccuracy = 10; // The difference between times. // It should be larger than kTimeAccuracy which is used in the method `XCTAssertEqualWithAccuracy`. @@ -145,7 +147,8 @@ - (void)testUpdateAuthState { NSString *updatedIDToken = [self idTokenWithExpireTime:updatedIDTokenExpireTime]; OIDAuthState *updatedAuthState = [OIDAuthState testInstanceWithIDToken:updatedIDToken accessToken:kNewAccessToken - accessTokenExpireTime:updatedAccessTokenExpireTime]; + accessTokenExpireTime:updatedAccessTokenExpireTime + refreshToken:kNewRefreshToken]; GIDProfileData *updatedProfileData = [GIDProfileData testInstance]; [user updateAuthState:updatedAuthState profileData:updatedProfileData]; @@ -156,6 +159,7 @@ - (void)testUpdateAuthState { XCTAssertEqualObjects(user.idToken.tokenString, updatedIDToken); XCTAssertEqualWithAccuracy([user.idToken.expirationDate timeIntervalSinceReferenceDate], updatedIDTokenExpireTime, kTimeAccuracy); + XCTAssertEqualObjects(user.refreshToken.tokenString, kNewRefreshToken); XCTAssertEqual(user.profile, updatedProfileData); XCTAssertEqual(_changesObserved, kChangeAll); } @@ -181,7 +185,8 @@ - (GIDGoogleUser *)googleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTok NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken - accessTokenExpireTime:accessTokenExpireTime]; + accessTokenExpireTime:accessTokenExpireTime + refreshToken:kRefreshToken]; return [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; } diff --git a/GoogleSignIn/Tests/Unit/GIDSignInTest.m b/GoogleSignIn/Tests/Unit/GIDSignInTest.m index 5d9dac77..fdcd1027 100644 --- a/GoogleSignIn/Tests/Unit/GIDSignInTest.m +++ b/GoogleSignIn/Tests/Unit/GIDSignInTest.m @@ -1202,6 +1202,7 @@ - (void)OAuthLoginWithAddScopesFlow:(BOOL)addScopesFlow [OIDTokenResponse testInstanceWithIDToken:[OIDTokenResponse fatIDToken] accessToken:restoredSignIn ? kAccessToken : nil expiresIn:oldAccessToken ? @(300) : nil + refreshToken:kRefreshToken tokenRequest:nil]; OIDTokenRequest *tokenRequest = [[OIDTokenRequest alloc] diff --git a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h index b255352f..f660e34e 100644 --- a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h +++ b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h @@ -30,6 +30,7 @@ + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken - accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime; + accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + refreshToken:(NSString *)refreshToken; @end diff --git a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m index 6c019820..a9f7c49c 100644 --- a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m +++ b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m @@ -35,13 +35,15 @@ + (instancetype)testInstanceWithTokenResponse:(OIDTokenResponse *)tokenResponse + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken - accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime { + accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + refreshToken:(NSString *)refreshToken { NSNumber *accessTokenExpiresIn = @(accessTokenExpireTime - [[NSDate date] timeIntervalSinceReferenceDate]); OIDTokenResponse *newResponse = [OIDTokenResponse testInstanceWithIDToken:idToken accessToken:accessToken expiresIn:accessTokenExpiresIn + refreshToken:refreshToken tokenRequest:nil]; return [self testInstanceWithTokenResponse:newResponse]; } diff --git a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h index 990fda0f..bd26a66a 100644 --- a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h +++ b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.h @@ -56,6 +56,7 @@ extern NSString * const kFatPictureURL; + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken expiresIn:(NSNumber *)expiresIn + refreshToken:(NSString *)refreshToken tokenRequest:(OIDTokenRequest *)tokenRequest; + (NSString *)idToken; diff --git a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m index 1e1b95bf..3f3df182 100644 --- a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m +++ b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m @@ -61,19 +61,21 @@ + (instancetype)testInstanceWithIDToken:(NSString *)idToken { return [OIDTokenResponse testInstanceWithIDToken:idToken accessToken:nil expiresIn:nil + refreshToken:kRefreshToken tokenRequest:nil]; } + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken expiresIn:(NSNumber *)expiresIn + refreshToken:(NSString *)refreshToken tokenRequest:(OIDTokenRequest *)tokenRequest { NSMutableDictionary *parameters; parameters = [[NSMutableDictionary alloc] initWithDictionary:@{ @"access_token" : accessToken ?: kAccessToken, @"expires_in" : expiresIn ?: @(kAccessTokenExpiresIn), @"token_type" : @"example_token_type", - @"refresh_token" : kRefreshToken, + @"refresh_token" : refreshToken, @"scope" : [OIDScopeUtilities scopesWithArray:@[ OIDAuthorizationRequestTestingScope2 ]], @"server_code" : kServerAuthCode, }]; From d45e398d697f2cffed73d1eb06b2cb4ceef781dc Mon Sep 17 00:00:00 2001 From: pinlu Date: Thu, 22 Sep 2022 14:25:29 -0700 Subject: [PATCH 5/9] Remove the KVO testing Since we use NSObject automatic change notifications we can remove the tests for manual notifications emission. --- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 91 +------------------ .../Tests/Unit/OIDTokenResponse+Testing.m | 4 +- 2 files changed, 5 insertions(+), 90 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 999d617d..aa326d35 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -43,45 +43,10 @@ // It should be larger than kTimeAccuracy which is used in the method `XCTAssertEqualWithAccuracy`. static NSTimeInterval const kTimeIncrement = 100; -// List of observed properties of the class being tested. -static NSString *const kObservedProperties[] = { - @"accessToken", - @"refreshToken", - @"idToken", -}; -static const NSUInteger kNumberOfObservedProperties = - sizeof(kObservedProperties) / sizeof(*kObservedProperties); - -// Bit position for notification change type bitmask flags. -// Must match the list of observed properties above. -typedef NS_ENUM(NSUInteger, ChangeType) { - kChangeTypeAccessTokenPrior, - kChangeTypeAccessToken, - kChangeTypeRefreshTokenPrior, - kChangeTypeRefreshToken, - kChangeTypeIDTokenPrior, - kChangeTypeIDToken, - kChangeTypeEnd // not a real change type but an end mark for calculating |kChangeAll| -}; - -static const NSUInteger kChangeAll = (1u << kChangeTypeEnd) - 1u; - -#if __has_feature(c_static_assert) || __has_extension(c_static_assert) -_Static_assert(kChangeTypeEnd == (sizeof(kObservedProperties) / sizeof(*kObservedProperties)) * 2, - "List of observed properties must match list of change notification enums"); -#endif - @interface GIDGoogleUserTest : XCTestCase @end -@implementation GIDGoogleUserTest { - // Bitmask flags for observed changes, as specified in |ChangeType|. - NSUInteger _changesObserved; -} - -- (void)setUp { - _changesObserved = 0; -} +@implementation GIDGoogleUserTest #pragma mark - Tests @@ -139,8 +104,8 @@ - (void)testUpdateAuthState { NSTimeInterval accessTokenExpireTime = [[NSDate date] timeIntervalSince1970]; NSTimeInterval idTokenExpireTime = accessTokenExpireTime + kTimeIncrement; - GIDGoogleUser *user = [self observedGoogleUserWithAccessTokenExpireTime:accessTokenExpireTime - idTokenExpireTime:idTokenExpireTime]; + GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime + idTokenExpireTime:idTokenExpireTime]; NSTimeInterval updatedAccessTokenExpireTime = idTokenExpireTime + kTimeIncrement; NSTimeInterval updatedIDTokenExpireTime = updatedAccessTokenExpireTime + kTimeIncrement; @@ -161,27 +126,12 @@ - (void)testUpdateAuthState { updatedIDTokenExpireTime, kTimeAccuracy); XCTAssertEqualObjects(user.refreshToken.tokenString, kNewRefreshToken); XCTAssertEqual(user.profile, updatedProfileData); - XCTAssertEqual(_changesObserved, kChangeAll); } #pragma mark - Helpers -- (GIDGoogleUser *)observedGoogleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime - idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { - GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime - idTokenExpireTime:idTokenExpireTime]; - for (unsigned int i = 0; i < kNumberOfObservedProperties; ++i) { - [user addObserver:self - forKeyPath:kObservedProperties[i] - options:NSKeyValueObservingOptionPrior - context:NULL]; - } - return user; -} - - (GIDGoogleUser *)googleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { - NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken @@ -196,39 +146,4 @@ - (NSString *)idTokenWithExpireTime:(NSTimeInterval)expireTime { return [OIDTokenResponse idTokenWithSub:kUserID exp:@(expireTime)]; } -#pragma mark - NSKeyValueObserving - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - ChangeType changeType; - if ([keyPath isEqualToString:@"accessToken"]) { - if (change[NSKeyValueChangeNotificationIsPriorKey]) { - changeType = kChangeTypeAccessTokenPrior; - } else { - changeType = kChangeTypeAccessToken; - } - } else if ([keyPath isEqualToString:@"refreshToken"]) { - if (change[NSKeyValueChangeNotificationIsPriorKey]) { - changeType = kChangeTypeRefreshTokenPrior; - } else { - changeType = kChangeTypeRefreshToken; - } - } else if ([keyPath isEqualToString:@"idToken"]) { - if (change[NSKeyValueChangeNotificationIsPriorKey]) { - changeType = kChangeTypeIDTokenPrior; - } else { - changeType = kChangeTypeIDToken; - } - } else { - XCTFail(@"unexpected keyPath"); - return; // so compiler knows |changeType| is always assigned - } - - NSInteger changeMask = 1 << changeType; - XCTAssertFalse(_changesObserved & changeMask); // each change type should only fire once - _changesObserved |= changeMask; -} - @end diff --git a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m index 3f3df182..49823be7 100644 --- a/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m +++ b/GoogleSignIn/Tests/Unit/OIDTokenResponse+Testing.m @@ -61,7 +61,7 @@ + (instancetype)testInstanceWithIDToken:(NSString *)idToken { return [OIDTokenResponse testInstanceWithIDToken:idToken accessToken:nil expiresIn:nil - refreshToken:kRefreshToken + refreshToken:nil tokenRequest:nil]; } @@ -75,7 +75,7 @@ + (instancetype)testInstanceWithIDToken:(NSString *)idToken @"access_token" : accessToken ?: kAccessToken, @"expires_in" : expiresIn ?: @(kAccessTokenExpiresIn), @"token_type" : @"example_token_type", - @"refresh_token" : refreshToken, + @"refresh_token" : refreshToken ?: kRefreshToken, @"scope" : [OIDScopeUtilities scopesWithArray:@[ OIDAuthorizationRequestTestingScope2 ]], @"server_code" : kServerAuthCode, }]; From a56786b6024cdb1edb31a432245d6d15c74a15b5 Mon Sep 17 00:00:00 2001 From: pinlu Date: Fri, 23 Sep 2022 15:10:51 -0700 Subject: [PATCH 6/9] Test tokens unchanged Added a new test case `testUpdateAuthStateWithUnchangedRefreshTokenAndIDToken ` --- GoogleSignIn/Sources/GIDGoogleUser.m | 14 ++++++------ GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 25 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/GoogleSignIn/Sources/GIDGoogleUser.m b/GoogleSignIn/Sources/GIDGoogleUser.m index 979a164f..cb215f7f 100644 --- a/GoogleSignIn/Sources/GIDGoogleUser.m +++ b/GoogleSignIn/Sources/GIDGoogleUser.m @@ -129,15 +129,15 @@ - (void)updateAuthState:(OIDAuthState *)authState } - (void)updateTokensWithAuthState:(OIDAuthState *)authState { - GIDToken *accessToken = [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken - expirationDate:authState.lastTokenResponse. - accessTokenExpirationDate]; + GIDToken *accessToken = + [[GIDToken alloc] initWithTokenString:authState.lastTokenResponse.accessToken + expirationDate:authState.lastTokenResponse.accessTokenExpirationDate]; if (![self.accessToken isEqualToToken:accessToken]) { self.accessToken = accessToken; } GIDToken *refreshToken = [[GIDToken alloc] initWithTokenString:authState.refreshToken - expirationDate:nil]; + expirationDate:nil]; if (![self.refreshToken isEqualToToken:refreshToken]) { self.refreshToken = refreshToken; } @@ -145,10 +145,10 @@ - (void)updateTokensWithAuthState:(OIDAuthState *)authState { GIDToken *idToken; NSString *idTokenString = authState.lastTokenResponse.idToken; if (idTokenString) { - NSDate *idTokenExpirationDate = [[[OIDIDToken alloc] - initWithIDTokenString:idTokenString] expiresAt]; + NSDate *idTokenExpirationDate = + [[[OIDIDToken alloc] initWithIDTokenString:idTokenString] expiresAt]; idToken = [[GIDToken alloc] initWithTokenString:idTokenString - expirationDate:idTokenExpirationDate]; + expirationDate:idTokenExpirationDate]; } else { idToken = nil; } diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index aa326d35..f356057b 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -128,6 +128,31 @@ - (void)testUpdateAuthState { XCTAssertEqual(user.profile, updatedProfileData); } +- (void)testUpdateAuthStateWithUnchangedRefreshTokenAndIDToken { + NSTimeInterval accessTokenExpireTime = [[NSDate date] timeIntervalSince1970]; + NSTimeInterval idTokenExpireTime = [[NSDate date] timeIntervalSince1970]; + + GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime + idTokenExpireTime:idTokenExpireTime]; + + GIDToken *accessTokenBeforeUpdate = user.accessToken; + GIDToken *refreshTokenBeforeUpdate = user.refreshToken; + GIDToken *idTokenBeforeUpdate = user.idToken; + + NSString *updatedIDToken = [self idTokenWithExpireTime:idTokenExpireTime]; + OIDAuthState *updatedAuthState = [OIDAuthState testInstanceWithIDToken:updatedIDToken + accessToken:kNewAccessToken + accessTokenExpireTime:accessTokenExpireTime + refreshToken:kRefreshToken]; + GIDProfileData *updatedProfileData = [GIDProfileData testInstance]; + + [user updateAuthState:updatedAuthState profileData:updatedProfileData]; + + XCTAssertIdentical(user.idToken, idTokenBeforeUpdate); + XCTAssertIdentical(user.refreshToken, refreshTokenBeforeUpdate); + XCTAssertNotIdentical(user.accessToken, accessTokenBeforeUpdate); +} + #pragma mark - Helpers - (GIDGoogleUser *)googleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime From 6ec86daa1997b4865f91c261c2a38171f9635f6d Mon Sep 17 00:00:00 2001 From: pinlu Date: Sun, 25 Sep 2022 18:49:36 -0700 Subject: [PATCH 7/9] Use accessTokenExpiresIn to replace accessTokenExpireTime in tests --- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 29 +++++++++---------- .../Tests/Unit/OIDAuthState+Testing.h | 8 ++++- .../Tests/Unit/OIDAuthState+Testing.m | 6 ++-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index f356057b..8333d303 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -101,27 +101,27 @@ - (void)testLegacyCoding { #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST - (void)testUpdateAuthState { - NSTimeInterval accessTokenExpireTime = [[NSDate date] timeIntervalSince1970]; - NSTimeInterval idTokenExpireTime = accessTokenExpireTime + kTimeIncrement; + NSTimeInterval idTokenExpireTime = [[NSDate date] timeIntervalSince1970]; - GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime - idTokenExpireTime:idTokenExpireTime]; + GIDGoogleUser *user = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn + idTokenExpireTime:idTokenExpireTime]; - NSTimeInterval updatedAccessTokenExpireTime = idTokenExpireTime + kTimeIncrement; - NSTimeInterval updatedIDTokenExpireTime = updatedAccessTokenExpireTime + kTimeIncrement; + NSTimeInterval updatedIDTokenExpireTime = idTokenExpireTime + kTimeIncrement; NSString *updatedIDToken = [self idTokenWithExpireTime:updatedIDTokenExpireTime]; OIDAuthState *updatedAuthState = [OIDAuthState testInstanceWithIDToken:updatedIDToken accessToken:kNewAccessToken - accessTokenExpireTime:updatedAccessTokenExpireTime + accessTokenExpiresIn:kAccessTokenExpiresIn refreshToken:kNewRefreshToken]; GIDProfileData *updatedProfileData = [GIDProfileData testInstance]; [user updateAuthState:updatedAuthState profileData:updatedProfileData]; XCTAssertEqualObjects(user.accessToken.tokenString, kNewAccessToken); + NSDate *expectedAccessTokenExpirationDate = [[NSDate date] dateByAddingTimeInterval:kAccessTokenExpiresIn]; XCTAssertEqualWithAccuracy([user.accessToken.expirationDate timeIntervalSince1970], - updatedAccessTokenExpireTime, kTimeAccuracy); + [expectedAccessTokenExpirationDate timeIntervalSince1970], kTimeAccuracy); XCTAssertEqualObjects(user.idToken.tokenString, updatedIDToken); + XCTAssertEqualWithAccuracy([user.idToken.expirationDate timeIntervalSince1970], updatedIDTokenExpireTime, kTimeAccuracy); XCTAssertEqualObjects(user.refreshToken.tokenString, kNewRefreshToken); @@ -129,11 +129,10 @@ - (void)testUpdateAuthState { } - (void)testUpdateAuthStateWithUnchangedRefreshTokenAndIDToken { - NSTimeInterval accessTokenExpireTime = [[NSDate date] timeIntervalSince1970]; NSTimeInterval idTokenExpireTime = [[NSDate date] timeIntervalSince1970]; - GIDGoogleUser *user = [self googleUserWithAccessTokenExpireTime:accessTokenExpireTime - idTokenExpireTime:idTokenExpireTime]; + GIDGoogleUser *user = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn + idTokenExpireTime:idTokenExpireTime]; GIDToken *accessTokenBeforeUpdate = user.accessToken; GIDToken *refreshTokenBeforeUpdate = user.refreshToken; @@ -142,7 +141,7 @@ - (void)testUpdateAuthStateWithUnchangedRefreshTokenAndIDToken { NSString *updatedIDToken = [self idTokenWithExpireTime:idTokenExpireTime]; OIDAuthState *updatedAuthState = [OIDAuthState testInstanceWithIDToken:updatedIDToken accessToken:kNewAccessToken - accessTokenExpireTime:accessTokenExpireTime + accessTokenExpiresIn:kAccessTokenExpiresIn refreshToken:kRefreshToken]; GIDProfileData *updatedProfileData = [GIDProfileData testInstance]; @@ -155,12 +154,12 @@ - (void)testUpdateAuthStateWithUnchangedRefreshTokenAndIDToken { #pragma mark - Helpers -- (GIDGoogleUser *)googleUserWithAccessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime - idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { +- (GIDGoogleUser *)googleUserWithAccessTokenExpiresIn:(NSTimeInterval)accessTokenExpiresIn + idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken - accessTokenExpireTime:accessTokenExpireTime + accessTokenExpiresIn:accessTokenExpiresIn refreshToken:kRefreshToken]; return [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; diff --git a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h index f660e34e..15feb758 100644 --- a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h +++ b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.h @@ -28,9 +28,15 @@ + (instancetype)testInstanceWithTokenResponse:(OIDTokenResponse *)tokenResponse; +/** + * @idToken The ID token. + * @accessToken The access token string. + * @accessTokenExipresIn The life time of the access token starting from the moment when `OIDTokenResponse` is created. + * @refreshToken The refresh token string. + */ + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken - accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + accessTokenExpiresIn:(NSTimeInterval)accessTokenExpiresIn refreshToken:(NSString *)refreshToken; @end diff --git a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m index b9082227..c6c694a4 100644 --- a/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m +++ b/GoogleSignIn/Tests/Unit/OIDAuthState+Testing.m @@ -35,14 +35,12 @@ + (instancetype)testInstanceWithTokenResponse:(OIDTokenResponse *)tokenResponse + (instancetype)testInstanceWithIDToken:(NSString *)idToken accessToken:(NSString *)accessToken - accessTokenExpireTime:(NSTimeInterval)accessTokenExpireTime + accessTokenExpiresIn:(NSTimeInterval)accessTokenExpiresIn refreshToken:(NSString *)refreshToken { - NSNumber *accessTokenExpiresIn = - @(accessTokenExpireTime - [[NSDate date] timeIntervalSince1970]); OIDTokenResponse *newResponse = [OIDTokenResponse testInstanceWithIDToken:idToken accessToken:accessToken - expiresIn:accessTokenExpiresIn + expiresIn:@(accessTokenExpiresIn) refreshToken:refreshToken tokenRequest:nil]; return [self testInstanceWithTokenResponse:newResponse]; From 338f244ab9eaa6191b372db26b9c5206347d789c Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 26 Sep 2022 11:46:15 -0700 Subject: [PATCH 8/9] Alignment --- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 03ddfdfb..4d467626 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -136,7 +136,7 @@ - (void)testUpdateAuthState_tokensAreNotChanged { NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken - accessTokenExpiresIn:kAccessTokenExpiresIn + accessTokenExpiresIn:kAccessTokenExpiresIn refreshToken:kRefreshToken]; GIDGoogleUser *user = [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; From 9743fb1254ebd73085125126420d9c5cf7f130ad Mon Sep 17 00:00:00 2001 From: pinlu Date: Mon, 26 Sep 2022 15:03:05 -0700 Subject: [PATCH 9/9] Improve helper method signature. Use expiresIn on both access toke and id token. --- GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m | 32 ++++++++++----------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m index 4d467626..1199fc48 100644 --- a/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m +++ b/GoogleSignIn/Tests/Unit/GIDGoogleUserTest.m @@ -39,9 +39,8 @@ static NSString *const kNewRefreshToken = @"new_refresh_token"; static NSTimeInterval const kTimeAccuracy = 10; -// The difference between times. -// It should be larger than kTimeAccuracy which is used in the method `XCTAssertEqualWithAccuracy`. -static NSTimeInterval const kTimeIncrement = 100; +static NSTimeInterval const kIDTokenExpiresIn = 100; +static NSTimeInterval const kNewIDTokenExpiresIn = 200; @interface GIDGoogleUserTest : XCTestCase @end @@ -101,13 +100,10 @@ - (void)testLegacyCoding { #endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST - (void)testUpdateAuthState { - NSTimeInterval idTokenExpireTime = [[NSDate date] timeIntervalSince1970]; - GIDGoogleUser *user = [self googleUserWithAccessTokenExpiresIn:kAccessTokenExpiresIn - idTokenExpireTime:idTokenExpireTime]; + idTokenExpiresIn:kIDTokenExpiresIn]; - NSTimeInterval updatedIDTokenExpireTime = idTokenExpireTime + kTimeIncrement; - NSString *updatedIDToken = [self idTokenWithExpireTime:updatedIDTokenExpireTime]; + NSString *updatedIDToken = [self idTokenWithExpiresIn:kNewIDTokenExpiresIn]; OIDAuthState *updatedAuthState = [OIDAuthState testInstanceWithIDToken:updatedIDToken accessToken:kNewAccessToken accessTokenExpiresIn:kAccessTokenExpiresIn @@ -120,20 +116,21 @@ - (void)testUpdateAuthState { NSDate *expectedAccessTokenExpirationDate = [[NSDate date] dateByAddingTimeInterval:kAccessTokenExpiresIn]; XCTAssertEqualWithAccuracy([user.accessToken.expirationDate timeIntervalSince1970], [expectedAccessTokenExpirationDate timeIntervalSince1970], kTimeAccuracy); - XCTAssertEqualObjects(user.idToken.tokenString, updatedIDToken); + XCTAssertEqualObjects(user.idToken.tokenString, updatedIDToken); + NSDate *expectedIDTokenExpirationDate = [[NSDate date] dateByAddingTimeInterval:kNewIDTokenExpiresIn]; XCTAssertEqualWithAccuracy([user.idToken.expirationDate timeIntervalSince1970], - updatedIDTokenExpireTime, kTimeAccuracy); + [expectedIDTokenExpirationDate timeIntervalSince1970], kTimeAccuracy); + XCTAssertEqualObjects(user.refreshToken.tokenString, kNewRefreshToken); + XCTAssertEqual(user.profile, updatedProfileData); } // When updating with a new OIDAuthState in which token information is not changed, the token objects // should remain the same. - (void)testUpdateAuthState_tokensAreNotChanged { - NSTimeInterval idTokenExpireTime = [[NSDate date] timeIntervalSince1970]; - - NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; + NSString *idToken = [self idTokenWithExpiresIn:kIDTokenExpiresIn]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken accessTokenExpiresIn:kAccessTokenExpiresIn @@ -155,8 +152,8 @@ - (void)testUpdateAuthState_tokensAreNotChanged { #pragma mark - Helpers - (GIDGoogleUser *)googleUserWithAccessTokenExpiresIn:(NSTimeInterval)accessTokenExpiresIn - idTokenExpireTime:(NSTimeInterval)idTokenExpireTime { - NSString *idToken = [self idTokenWithExpireTime:idTokenExpireTime]; + idTokenExpiresIn:(NSTimeInterval)idTokenExpiresIn { + NSString *idToken = [self idTokenWithExpiresIn:idTokenExpiresIn]; OIDAuthState *authState = [OIDAuthState testInstanceWithIDToken:idToken accessToken:kAccessToken accessTokenExpiresIn:accessTokenExpiresIn @@ -165,8 +162,9 @@ - (GIDGoogleUser *)googleUserWithAccessTokenExpiresIn:(NSTimeInterval)accessToke return [[GIDGoogleUser alloc] initWithAuthState:authState profileData:nil]; } -// The expireTime should be based on 1970. -- (NSString *)idTokenWithExpireTime:(NSTimeInterval)expireTime { +- (NSString *)idTokenWithExpiresIn:(NSTimeInterval)expiresIn { + // The expireTime should be based on 1970. + NSTimeInterval expireTime = [[NSDate date] timeIntervalSince1970] + expiresIn; return [OIDTokenResponse idTokenWithSub:kUserID exp:@(expireTime)]; }