Skip to content

Commit afef1f8

Browse files
committed
g-orchestrated: add automation test hooks to the SignInSample
1 parent 8c83afa commit afef1f8

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

‎Samples/ObjC/SignInSample/Source/SignInViewController.m‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717
#import "SignInViewController.h"
1818

1919
@import GoogleSignIn;
20+
@import AppAuth;
21+
@import GTMAppAuth;
2022

2123
#import "AuthInspectorViewController.h"
2224
#import "DataPickerState.h"
2325
#import "DataPickerViewController.h"
2426
#import <AppAuth/OIDTokenUtilities.h>
27+
#import <CommonCrypto/CommonDigest.h>
2528

2629
static NSString *const kSignInViewTitle = @"Sign-In Sample";
2730
static NSString *const kPlaceholderUserName = @"<Name>";
@@ -38,6 +41,14 @@
3841
// Accessibility Identifiers.
3942
static NSString *const kCredentialsButtonAccessibilityIdentifier = @"Credentials";
4043

44+
@interface SignInViewController ()
45+
46+
- (void)logTestStateForEvent:(NSString *)event;
47+
- (nullable NSString *)fingerprintForToken:(nullable NSString *)token;
48+
- (void)forceTokenRefresh;
49+
50+
@end
51+
4152
@implementation SignInViewController {
4253
// This is an array of arrays, each one corresponding to the cell
4354
// labels for its respective section.
@@ -114,7 +125,23 @@ - (id)initWithCoder:(NSCoder *)aDecoder {
114125
- (void)viewDidLoad {
115126
[super viewDidLoad];
116127

128+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
129+
if ([defaults boolForKey:@"GSITestSignOutOnLaunch"]) {
130+
[GIDSignIn.sharedInstance signOut];
131+
NSLog(@"SignInSample test hook: signed out on launch");
132+
}
133+
134+
self.signInButton.accessibilityIdentifier = @"sign_in_button";
135+
self.signOutButton.accessibilityIdentifier = @"sign_out_button";
136+
self.disconnectButton.accessibilityIdentifier = @"disconnect_button";
137+
self.addScopesButton.accessibilityIdentifier = @"add_scopes_button";
117138
self.credentialsButton.accessibilityIdentifier = kCredentialsButtonAccessibilityIdentifier;
139+
140+
[self logTestStateForEvent:@"launch"];
141+
142+
if ([defaults boolForKey:@"GSITestForceRefreshOnLaunch"]) {
143+
[self forceTokenRefresh];
144+
}
118145
}
119146

120147
- (void)viewWillAppear:(BOOL)animated {
@@ -184,6 +211,7 @@ - (void)reportAuthStatus {
184211
}
185212

186213
[self refreshUserInfo];
214+
[self logTestStateForEvent:@"state_changed"];
187215
}
188216

189217
// Update the interface elements containing user data to reflect the
@@ -432,4 +460,90 @@ - (void)tableView:(UITableView *)tableView
432460
[self.navigationController pushViewController:dataPicker animated:YES];
433461
}
434462

463+
#pragma mark - Test hooks
464+
465+
- (void)logTestStateForEvent:(NSString *)event {
466+
GIDGoogleUser *currentUser = GIDSignIn.sharedInstance.currentUser;
467+
BOOL signedIn = (currentUser != nil);
468+
BOOL hasRefreshToken = (currentUser.refreshToken.tokenString.length > 0);
469+
NSString *accessTokenFingerprint = [self fingerprintForToken:currentUser.accessToken.tokenString];
470+
471+
NSString *accessTokenExpiration = nil;
472+
if (currentUser.accessToken.expirationDate) {
473+
NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
474+
accessTokenExpiration = [formatter stringFromDate:currentUser.accessToken.expirationDate];
475+
}
476+
477+
NSInteger grantedScopeCount = currentUser.grantedScopes.count;
478+
479+
NSDictionary *state = @{
480+
@"event": event,
481+
@"signedIn": @(signedIn),
482+
@"hasRefreshToken": @(hasRefreshToken),
483+
@"accessTokenFingerprint": accessTokenFingerprint ?: [NSNull null],
484+
@"accessTokenExpiration": accessTokenExpiration ?: [NSNull null],
485+
@"grantedScopeCount": @(grantedScopeCount)
486+
};
487+
488+
NSError *error;
489+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:state options:0 error:&error];
490+
if (jsonData) {
491+
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
492+
NSLog(@"GSI_TEST_STATE %@", jsonString);
493+
}
494+
}
495+
496+
- (nullable NSString *)fingerprintForToken:(nullable NSString *)token {
497+
if (token.length == 0) {
498+
return nil;
499+
}
500+
NSData *data = [token dataUsingEncoding:NSUTF8StringEncoding];
501+
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
502+
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
503+
NSMutableString *output = [NSMutableString stringWithCapacity:8];
504+
for (int i = 0; i < 4; i++) {
505+
[output appendFormat:@"%02x", digest[i]];
506+
}
507+
return output;
508+
}
509+
510+
- (void)forceTokenRefresh {
511+
GIDGoogleUser *currentUser = GIDSignIn.sharedInstance.currentUser;
512+
if (!currentUser) {
513+
NSLog(@"SignInSample test hook: force refresh skipped, not signed in");
514+
return;
515+
}
516+
517+
id<GTMFetcherAuthorizationProtocol> authorizer = currentUser.fetcherAuthorizer;
518+
if (![authorizer isKindOfClass:[GTMAuthSession class]]) {
519+
NSLog(@"SignInSample test hook: fetcherAuthorizer is not a GTMAuthSession");
520+
return;
521+
}
522+
523+
GTMAuthSession *authSession = (GTMAuthSession *)authorizer;
524+
NSString *oldFingerprint = [self fingerprintForToken:currentUser.accessToken.tokenString];
525+
526+
[authSession.authState setNeedsTokenRefresh];
527+
__weak SignInViewController *weakSelf = self;
528+
[authSession.authState performActionWithFreshTokens:^(NSString *_Nullable accessToken,
529+
NSString *_Nullable idToken,
530+
NSError *_Nullable error) {
531+
dispatch_async(dispatch_get_main_queue(), ^{
532+
SignInViewController *strongSelf = weakSelf;
533+
if (!strongSelf) return;
534+
535+
if (error) {
536+
NSLog(@"SignInSample test hook: force refresh failed: %@", error.localizedDescription);
537+
} else {
538+
NSString *newFingerprint = [strongSelf fingerprintForToken:
539+
GIDSignIn.sharedInstance.currentUser.accessToken.tokenString];
540+
NSLog(@"SignInSample test hook: force refresh succeeded; "
541+
"access token fingerprint %@ -> %@",
542+
oldFingerprint, newFingerprint);
543+
}
544+
[strongSelf logTestStateForEvent:@"force_refresh"];
545+
});
546+
}];
547+
}
548+
435549
@end

0 commit comments

Comments
 (0)