Skip to content

Commit 162e754

Browse files
Add more token tests (#7776)
1 parent 30335a3 commit 162e754

9 files changed

+983
-15
lines changed

FirebaseMessaging/Sources/Token/FIRMessagingTokenManager.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333

3434
@interface FIRMessagingTokenManager () {
3535
FIRMessagingTokenStore *_tokenStore;
36-
FIRMessagingCheckinStore *_checkinStore;
3736
NSString *_defaultFCMToken;
3837
}
3938

39+
@property(nonatomic, readwrite, strong) FIRMessagingCheckinStore *checkinStore;
4040
@property(nonatomic, readwrite, strong) FIRMessagingAuthService *authService;
4141
@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations;
4242

FirebaseMessaging/Tests/UnitTests/FIRMessagingBackupExcludedPlistTest.m

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,4 @@ - (BOOL)doesPlistFileExist {
9999
NSString *plistPath = [NSString pathWithComponents:components];
100100
return [[NSFileManager defaultManager] fileExistsAtPath:plistPath];
101101
}
102-
103-
- (BOOL)isPlistInDocumentsDirectory {
104-
NSArray *directoryPaths =
105-
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
106-
NSString *documentsSupportDirPath = directoryPaths.lastObject;
107-
NSArray *components =
108-
@[ documentsSupportDirPath, [NSString stringWithFormat:@"%@.plist", kTestPlistFileName] ];
109-
NSString *plistPath = [NSString pathWithComponents:components];
110-
return [[NSFileManager defaultManager] fileExistsAtPath:plistPath];
111-
}
112-
113102
@end

FirebaseMessaging/Tests/UnitTests/FIRMessagingCheckinStoreTest.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ + (BOOL)createSubDirectory:(NSString *)subDirectoryName;
4141
@end
4242

4343
// Testing constants
44-
static NSString *const kFakeCheckinPlistName = @"com.google.test.IIDStoreTestCheckin";
44+
static NSString *const kFakeCheckinPlistName = @"com.google.test.TestCheckin";
4545
static NSString *const kSubDirectoryName = @"FirebaseInstanceIDCheckinTest";
4646

4747
static NSString *const kAuthID = @"test-auth-id";
@@ -193,7 +193,8 @@ - (BOOL)savePreferencesToPlist:(NSDictionary *)preferences {
193193
}
194194

195195
- (NSString *)pathForCheckinPlist {
196-
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
196+
NSArray *paths =
197+
NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES);
197198
NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", kFakeCheckinPlistName];
198199
return [paths[0] stringByAppendingPathComponent:plistNameWithExtension];
199200
}

FirebaseMessaging/Tests/UnitTests/FIRMessagingServiceTest.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
#import <GoogleUtilities/GULUserDefaults.h>
2121
#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h"
22-
#import "FirebaseMessaging/Sources/FIRMessagingClient.h"
2322
#import "FirebaseMessaging/Sources/FIRMessagingPubSub.h"
2423
#import "FirebaseMessaging/Sources/FIRMessagingTopicsCommon.h"
2524
#import "FirebaseMessaging/Sources/NSError+FIRMessaging.h"
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright 2021 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 "FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.h"
18+
19+
#import <XCTest/XCTest.h>
20+
21+
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
22+
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
23+
#import "FirebaseMessaging/Sources/Token/FIRMessagingAPNSInfo.h"
24+
#import "OCMock.h"
25+
26+
static NSString *const kAuthorizedEntity = @"authorizedEntity";
27+
static NSString *const kScope = @"scope";
28+
static NSString *const kToken = @"eMP633ZkDYA:APA91bGfnlnbinRVE7nUwJSr_k6cuSTKectOlt66dKv1r_-"
29+
@"9Qvhy9XljAI62QPw307rgA0MaFHPnrU5sFxGZvsncRnkfuciwTUeyRpPNDZMFhNXt"
30+
@"7h1BKq9Wb2A0LAANpQefrPHVUp4p";
31+
static NSString *const kFirebaseAppID = @"firebaseAppID";
32+
static NSString *const kIID = @"eMP633ZkDYA";
33+
static BOOL const kAPNSSandbox = NO;
34+
35+
@interface FIRMessagingTokenInfoTest : XCTestCase
36+
37+
@property(nonatomic, strong) NSData *APNSDeviceToken;
38+
@property(nonatomic, strong) FIRMessagingTokenInfo *validTokenInfo;
39+
@property(nonatomic, strong) id mockOptions;
40+
41+
@end
42+
43+
@implementation FIRMessagingTokenInfoTest
44+
45+
- (void)setUp {
46+
[super setUp];
47+
48+
self.APNSDeviceToken = [@"validDeviceToken" dataUsingEncoding:NSUTF8StringEncoding];
49+
50+
self.mockOptions = OCMClassMock([FIROptions class]);
51+
OCMStub([self.mockOptions defaultOptionsDictionary]).andReturn(@{
52+
kFIRGoogleAppID : kFirebaseAppID
53+
});
54+
55+
self.validTokenInfo =
56+
[[FIRMessagingTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
57+
scope:kScope
58+
token:kToken
59+
appVersion:FIRMessagingCurrentAppVersion()
60+
firebaseAppID:FIRMessagingFirebaseAppID()];
61+
self.validTokenInfo.APNSInfo =
62+
[[FIRMessagingAPNSInfo alloc] initWithDeviceToken:self.APNSDeviceToken
63+
isSandbox:kAPNSSandbox];
64+
self.validTokenInfo.cacheTime = [NSDate date];
65+
66+
[[NSUserDefaults standardUserDefaults] setObject:FIRMessagingCurrentLocale()
67+
forKey:kFIRMessagingInstanceIDUserDefaultsKeyLocale];
68+
}
69+
70+
- (void)tearDown {
71+
[self.mockOptions stopMocking];
72+
[super tearDown];
73+
}
74+
75+
// Test that archiving a FIRMessagingTokenInfo object and restoring it from the archive
76+
// yields the same values for all the fields.
77+
- (void)testTokenInfoEncodingAndDecoding {
78+
FIRMessagingTokenInfo *info = self.validTokenInfo;
79+
#pragma clang diagnostic push
80+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
81+
NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:info];
82+
FIRMessagingTokenInfo *restoredInfo = [NSKeyedUnarchiver unarchiveObjectWithData:archive];
83+
#pragma clang diagnostic pop
84+
XCTAssertEqualObjects(restoredInfo.authorizedEntity, info.authorizedEntity);
85+
XCTAssertEqualObjects(restoredInfo.scope, info.scope);
86+
XCTAssertEqualObjects(restoredInfo.token, info.token);
87+
XCTAssertEqualObjects(restoredInfo.appVersion, info.appVersion);
88+
XCTAssertEqualObjects(restoredInfo.firebaseAppID, info.firebaseAppID);
89+
XCTAssertEqualObjects(restoredInfo.cacheTime, info.cacheTime);
90+
XCTAssertEqualObjects(restoredInfo.APNSInfo.deviceToken, info.APNSInfo.deviceToken);
91+
XCTAssertEqual(restoredInfo.APNSInfo.sandbox, info.APNSInfo.sandbox);
92+
}
93+
94+
// Test that archiving a FIRMessagingTokenInfo object with missing fields and restoring it
95+
// from the archive yields the same values for all the fields.
96+
- (void)testTokenInfoEncodingAndDecodingWithMissingFields {
97+
// Don't include appVersion, firebaseAppID, APNSInfo and cacheTime
98+
FIRMessagingTokenInfo *sparseInfo =
99+
[[FIRMessagingTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
100+
scope:kScope
101+
token:kToken
102+
appVersion:nil
103+
firebaseAppID:nil];
104+
#pragma clang diagnostic push
105+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
106+
NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:sparseInfo];
107+
FIRMessagingTokenInfo *restoredInfo = [NSKeyedUnarchiver unarchiveObjectWithData:archive];
108+
#pragma clang diagnostic pop
109+
XCTAssertEqualObjects(restoredInfo.authorizedEntity, sparseInfo.authorizedEntity);
110+
XCTAssertEqualObjects(restoredInfo.scope, sparseInfo.scope);
111+
XCTAssertEqualObjects(restoredInfo.token, sparseInfo.token);
112+
XCTAssertNil(restoredInfo.appVersion);
113+
XCTAssertNil(restoredInfo.firebaseAppID);
114+
XCTAssertNil(restoredInfo.cacheTime);
115+
XCTAssertNil(restoredInfo.APNSInfo);
116+
}
117+
118+
- (void)testTokenFreshnessWithLocaleChange {
119+
// Default should be fresh because we mock last fetch token time just now.
120+
XCTAssertTrue([self.validTokenInfo isFreshWithIID:kIID]);
121+
122+
// Locale change should affect token refreshness.
123+
// Set to a different locale than the current locale.
124+
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hant"
125+
forKey:kFIRMessagingInstanceIDUserDefaultsKeyLocale];
126+
[[NSUserDefaults standardUserDefaults] synchronize];
127+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
128+
// Reset locale
129+
[[NSUserDefaults standardUserDefaults] setObject:FIRMessagingCurrentLocale()
130+
forKey:kFIRMessagingInstanceIDUserDefaultsKeyLocale];
131+
[[NSUserDefaults standardUserDefaults] synchronize];
132+
}
133+
134+
- (void)testTokenFreshnessWithTokenTimestampChange {
135+
XCTAssertTrue([self.validTokenInfo isFreshWithIID:kIID]);
136+
// Set last fetch token time 7 days ago.
137+
NSTimeInterval lastFetchTokenTimestamp =
138+
FIRMessagingCurrentTimestampInSeconds() - 7 * 24 * 60 * 60;
139+
self.validTokenInfo.cacheTime = [NSDate dateWithTimeIntervalSince1970:lastFetchTokenTimestamp];
140+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
141+
142+
// Set last fetch token time more than 7 days ago.
143+
lastFetchTokenTimestamp = FIRMessagingCurrentTimestampInSeconds() - 8 * 24 * 60 * 60;
144+
self.validTokenInfo.cacheTime = [NSDate dateWithTimeIntervalSince1970:lastFetchTokenTimestamp];
145+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
146+
147+
// Set last fetch token time nil to mock legacy storage format. Token should be considered not
148+
// fresh.
149+
self.validTokenInfo.cacheTime = nil;
150+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
151+
}
152+
153+
- (void)testTokenFreshnessWithFirebaseAppIDChange {
154+
XCTAssertTrue([self.validTokenInfo isFreshWithIID:kIID]);
155+
// Change Firebase App ID.
156+
[FIROptions defaultOptions].googleAppID = @"newFirebaseAppID:ios:abcdefg";
157+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
158+
}
159+
160+
- (void)testTokenFreshnessWithAppVersionChange {
161+
XCTAssertTrue([self.validTokenInfo isFreshWithIID:kIID]);
162+
// Change app version.
163+
self.validTokenInfo =
164+
[[FIRMessagingTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
165+
scope:kScope
166+
token:kToken
167+
appVersion:@"1.1"
168+
firebaseAppID:FIRMessagingFirebaseAppID()];
169+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
170+
}
171+
172+
- (void)testTokenInconsistentWithIID {
173+
XCTAssertTrue([self.validTokenInfo isFreshWithIID:kIID]);
174+
// Change token.
175+
self.validTokenInfo = [[FIRMessagingTokenInfo alloc]
176+
initWithAuthorizedEntity:kAuthorizedEntity
177+
scope:kScope
178+
token:@"cxhhwVY27AE:APA91bGfnlnbinRVE7nUwJSr_k6cuSTKectOlt66dKv1r_-"
179+
@"9Qvhy9XljAI62QPw307rgA0MaFHPnrU5sFxGZvsncRnkfuciwTUeyRpPNDZMFhNXt7"
180+
@"h1BKq9Wb2A0LAANpQefrPHVUp4p"
181+
appVersion:@"1.1"
182+
firebaseAppID:FIRMessagingFirebaseAppID()];
183+
XCTAssertFalse([self.validTokenInfo isFreshWithIID:kIID]);
184+
}
185+
@end

FirebaseMessaging/Tests/UnitTests/FIRMessagingTokenManagerTest.m

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#import <XCTest/XCTest.h>
1818
#import "OCMock.h"
1919

20+
#import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinPreferences.h"
21+
#import "FirebaseMessaging/Sources/Token/FIRMessagingCheckinStore.h"
2022
#import "FirebaseMessaging/Sources/Token/FIRMessagingTokenManager.h"
2123
#import "FirebaseMessaging/Tests/UnitTests/FIRMessagingTestUtilities.h"
2224

@@ -26,12 +28,21 @@ @interface FIRMessaging (ExposedForTest)
2628

2729
@end
2830

31+
@interface FIRMessagingTokenManager (ExposedForTest)
32+
33+
@property(nonatomic, readwrite, strong) FIRMessagingCheckinStore *checkinStore;
34+
35+
- (void)resetCredentialsIfNeeded;
36+
37+
@end
38+
2939
@interface FIRMessagingTokenManagerTest : XCTestCase {
3040
FIRMessaging *_messaging;
3141
id _mockMessaging;
3242
id _mockPubSub;
3343
id _mockTokenManager;
3444
id _mockInstallations;
45+
id _mockCheckinStore;
3546
FIRMessagingTestUtilities *_testUtil;
3647
}
3748

@@ -48,6 +59,7 @@ - (void)setUp {
4859
_mockMessaging = _testUtil.mockMessaging;
4960
_messaging = _testUtil.messaging;
5061
_mockTokenManager = _testUtil.mockTokenManager;
62+
_mockCheckinStore = OCMPartialMock(_messaging.tokenManager.checkinStore);
5163
}
5264

5365
- (void)tearDown {
@@ -96,4 +108,32 @@ - (void)testTokenChangeMethod {
96108
XCTAssertFalse([_messaging.tokenManager hasTokenChangedFromOldToken:oldToken
97109
toNewToken:newToken]);
98110
}
111+
112+
- (void)testResetCredentialsWithNoCachedCheckin {
113+
id niceMockCheckinStore = [OCMockObject niceMockForClass:[FIRMessagingCheckinStore class]];
114+
[[niceMockCheckinStore reject]
115+
removeCheckinPreferencesWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
116+
// Always setting up stub after expect.
117+
OCMStub([_mockCheckinStore cachedCheckinPreferences]).andReturn(nil);
118+
119+
[_messaging.tokenManager resetCredentialsIfNeeded];
120+
121+
OCMVerifyAll(niceMockCheckinStore);
122+
}
123+
124+
- (void)testResetCredentialsWithFreshInstall {
125+
FIRMessagingCheckinPreferences *checkinPreferences =
126+
[[FIRMessagingCheckinPreferences alloc] initWithDeviceID:@"test-auth-id"
127+
secretToken:@"test-secret"];
128+
// Expect checkin is removed if it's a fresh install.
129+
[[_mockCheckinStore expect]
130+
removeCheckinPreferencesWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
131+
// Always setting up stub after expect.
132+
OCMStub([_mockCheckinStore cachedCheckinPreferences]).andReturn(checkinPreferences);
133+
// Plist file doesn't exist, meaning this is a fresh install.
134+
OCMStub([_mockCheckinStore hasCheckinPlist]).andReturn(NO);
135+
136+
[_messaging.tokenManager resetCredentialsIfNeeded];
137+
OCMVerifyAll(_mockCheckinStore);
138+
}
99139
@end

0 commit comments

Comments
 (0)