GIDFakeMainBundle.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #if __has_include(<UIKit/UIKit.h>)
  15. #import <UIKit/UIKit.h>
  16. #endif
  17. #import "GoogleSignIn/Tests/Unit/GIDFakeMainBundle.h"
  18. #import <GoogleUtilities/GULSwizzler.h>
  19. #import <GoogleUtilities/GULSwizzler+Unswizzle.h>
  20. static NSString *const kCFBundleURLTypesKey = @"CFBundleURLTypes";
  21. static NSString *const kCFBundleURLSchemesKey = @"CFBundleURLSchemes";
  22. @implementation GIDFakeMainBundle {
  23. // Represents the CFBundleURLTypes of the mocked app bundle's info.plist.
  24. __block NSArray *_fakeSupportedSchemes;
  25. NSString *_clientId;
  26. NSString *_bundleId;
  27. }
  28. - (void)startFakingWithBundleId:(NSString *)bundleId clientId:(NSString *)clientId {
  29. _bundleId = bundleId;
  30. _clientId = clientId;
  31. [GULSwizzler swizzleClass:[NSBundle class]
  32. selector:@selector(objectForInfoDictionaryKey:)
  33. isClassSelector:NO
  34. withBlock:^(id _self, NSString *key) {
  35. if ([key isEqual:kCFBundleURLTypesKey]) {
  36. return self->_fakeSupportedSchemes;
  37. } else {
  38. @throw [NSException exceptionWithName:@"Requested unexpected info.plist key."
  39. reason:nil
  40. userInfo:nil];
  41. }
  42. }];
  43. }
  44. - (void)stopFaking {
  45. [GULSwizzler unswizzleClass:[NSBundle class]
  46. selector:@selector(objectForInfoDictionaryKey:)
  47. isClassSelector:NO];
  48. _fakeSupportedSchemes = nil;
  49. }
  50. #pragma mark - Utilities
  51. /**
  52. * @fn reversedClientId
  53. * @return The reversed version of _clientID.
  54. */
  55. - (NSString *)reversedClientId {
  56. NSArray *clientIdComponents = [_clientId.lowercaseString componentsSeparatedByString:@"."];
  57. NSArray *reversedClientIdComponents = [clientIdComponents reverseObjectEnumerator].allObjects;
  58. NSString *reversedClientId = [reversedClientIdComponents componentsJoinedByString:@"."];
  59. return reversedClientId;
  60. }
  61. /**
  62. * @fn stringByFlippingCasesInString:
  63. * @param original The string to flip cases for.
  64. * @return A string with A-Z replaced by a-z and a-z replaced by A-Z.
  65. */
  66. - (NSString *)stringByFlippingCasesInString:(NSString *)original {
  67. const unichar A = 'A';
  68. const unichar Z = 'Z';
  69. const unichar a = 'a';
  70. const unichar z = 'z';
  71. NSMutableString *flipped = [NSMutableString string];
  72. for (unsigned int i = 0; i < original.length; i++) {
  73. unichar c = [original characterAtIndex:i];
  74. if (A <= c && c <= Z) {
  75. c += a - A;
  76. } else if (a <= c && c <= z) {
  77. c -= a - A;
  78. }
  79. [flipped appendString:[NSString stringWithFormat:@"%c", c]];
  80. }
  81. return flipped;
  82. }
  83. #pragma mark - URL Schemes
  84. - (void)fakeAllSchemesSupported {
  85. _fakeSupportedSchemes = @[
  86. @{
  87. kCFBundleURLSchemesKey : @[ _bundleId ]
  88. },
  89. @{
  90. kCFBundleURLSchemesKey : @[ [self reversedClientId] ]
  91. }
  92. ];
  93. }
  94. - (void)fakeAllSchemesSupportedAndMerged {
  95. _fakeSupportedSchemes = @[
  96. @{
  97. kCFBundleURLSchemesKey : @[
  98. _bundleId,
  99. [self reversedClientId]
  100. ]
  101. },
  102. ];
  103. }
  104. - (void)fakeAllSchemesSupportedWithCasesMangled {
  105. NSString *caseFlippedBundleId =
  106. [self stringByFlippingCasesInString:_bundleId];
  107. NSString *caseFlippedReverseClientId =
  108. [self stringByFlippingCasesInString:[self reversedClientId]];
  109. _fakeSupportedSchemes = @[
  110. @{
  111. kCFBundleURLSchemesKey : @[ caseFlippedBundleId ]
  112. },
  113. @{
  114. kCFBundleURLSchemesKey : @[ caseFlippedReverseClientId ]
  115. }
  116. ];
  117. }
  118. - (void)fakeMissingClientIdScheme {
  119. _fakeSupportedSchemes = @[
  120. @{
  121. kCFBundleURLSchemesKey : @[ _bundleId ]
  122. }
  123. ];
  124. }
  125. - (void)fakeMissingAllSchemes {
  126. _fakeSupportedSchemes = nil;
  127. }
  128. - (void)fakeOtherSchemes {
  129. _fakeSupportedSchemes = @[
  130. @{
  131. kCFBundleURLSchemesKey : @[ @"junk" ]
  132. }
  133. ];
  134. }
  135. - (void)fakeOtherSchemesAndAllSchemes {
  136. _fakeSupportedSchemes = @[
  137. @{
  138. kCFBundleURLSchemesKey : @[ _bundleId ]
  139. },
  140. @{
  141. kCFBundleURLSchemesKey : @[ @"junk" ]
  142. },
  143. @{
  144. kCFBundleURLSchemesKey : @[ [self reversedClientId] ]
  145. }
  146. ];
  147. }
  148. @end