Files

295 lines
12 KiB
Objective-C
Raw Permalink Normal View History

2019-08-21 14:26:41 -07:00
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <XCTest/XCTest.h>
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
2019-08-21 14:26:41 -07:00
#import "FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.h"
2019-09-11 10:55:39 -07:00
#import "FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h"
2019-08-21 14:26:41 -07:00
#import "FirebaseRemoteConfig/Tests/Unit/RCNTestUtilities.h"
@import FirebaseRemoteConfigInterop;
2019-08-21 14:26:41 -07:00
@interface FIRRemoteConfigComponentTest : XCTestCase
@end
@implementation FIRRemoteConfigComponentTest {
/// Strong references to test apps. `FIRRemoteConfigComponent` holds its app weakly, and apps
/// created outside of `+[FIRApp configure...]` are not retained by `FIRApp`, so they must be
/// kept alive for the duration of each test.
NSMutableArray<FIRApp *> *_apps;
}
- (void)setUp {
[super setUp];
_apps = [[NSMutableArray alloc] init];
}
2019-08-21 14:26:41 -07:00
- (void)tearDown {
_apps = nil;
2019-08-21 14:26:41 -07:00
[super tearDown];
// Clear out any apps that were called with `configure`.
[FIRApp resetApps];
[FIRRemoteConfigComponent clearAllComponentInstances];
2019-08-21 14:26:41 -07:00
}
- (void)testRCInstanceCreationAndCaching {
// Create the provider to vend Remote Config instances.
FIRRemoteConfigComponent *provider = [self providerForTest];
// Create a Remote Config instance from the provider.
NSString *sharedNamespace = @"some_namespace";
FIRRemoteConfig *config = [provider remoteConfigForNamespace:sharedNamespace];
XCTAssertNotNil(config);
// Fetch an instance with the same namespace - should be the same instance.
FIRRemoteConfig *sameConfig = [provider remoteConfigForNamespace:sharedNamespace];
XCTAssertNotNil(sameConfig);
XCTAssertEqual(config, sameConfig);
}
- (void)testRCSeparateInstancesForDifferentNamespaces {
// Create the provider to vend Remote Config instances.
FIRRemoteConfigComponent *provider = [self providerForTest];
// Create a Remote Config instance from the provider.
FIRRemoteConfig *config = [provider remoteConfigForNamespace:@"namespace1"];
XCTAssertNotNil(config);
// Fetch another instance with a different namespace.
FIRRemoteConfig *config2 = [provider remoteConfigForNamespace:@"namespace2"];
XCTAssertNotNil(config2);
XCTAssertNotEqual(config, config2);
}
- (void)testRCSeparateInstancesForDifferentApps {
FIRRemoteConfigComponent *provider = [self providerForTest];
// Create a Remote Config instance from the provider.
NSString *sharedNamespace = @"some_namespace";
FIRRemoteConfig *config = [provider remoteConfigForNamespace:sharedNamespace];
XCTAssertNotNil(config);
// Use a new app and new provider, ensure the instances with the same namespace are different.
2019-08-21 14:26:41 -07:00
NSString *secondAppName = [provider.app.name stringByAppendingString:@"2"];
FIRApp *secondApp = [self retainedAppWithName:secondAppName options:[self fakeOptions]];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *separateProvider =
[[FIRRemoteConfigComponent alloc] initWithApp:secondApp];
FIRRemoteConfig *separateConfig = [separateProvider remoteConfigForNamespace:sharedNamespace];
XCTAssertNotNil(separateConfig);
XCTAssertNotEqual(config, separateConfig);
}
- (void)testInitialization {
// Explicitly instantiate the component here in case the providerForTest ever changes to mock
// something.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:[self fakeOptions]];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *provider = [[FIRRemoteConfigComponent alloc] initWithApp:app];
XCTAssertNotNil(provider);
XCTAssertNotNil(provider.app);
}
- (void)testRegistersAsLibrary {
// Now component has two register, one is provider and another one is Interop
XCTAssertEqual([FIRRemoteConfigComponent componentsToRegister].count, 2);
2019-08-21 14:26:41 -07:00
// Configure a test FIRApp for fetching an instance of the FIRRemoteConfigProvider.
NSString *appName = [self generatedTestAppName];
[FIRApp configureWithName:appName options:[self fakeOptions]];
FIRApp *app = [FIRApp appNamed:appName];
// Attempt to fetch the component and verify it's a valid instance.
id<FIRRemoteConfigProvider> provider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container);
id<FIRRemoteConfigInterop> interop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container);
2019-08-21 14:26:41 -07:00
XCTAssertNotNil(provider);
XCTAssertNotNil(interop);
2019-08-21 14:26:41 -07:00
// Ensure that the instance that comes from the container is cached.
id<FIRRemoteConfigProvider> sameProvider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container);
id<FIRRemoteConfigInterop> sameInterop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container);
2019-08-21 14:26:41 -07:00
XCTAssertNotNil(sameProvider);
XCTAssertNotNil(sameInterop);
2019-08-21 14:26:41 -07:00
XCTAssertEqual(provider, sameProvider);
XCTAssertEqual(interop, sameInterop);
// Dynamic typing, both prototols are referring to the same component instance
id providerID = provider;
id interopID = interop;
XCTAssertEqualObjects(providerID, interopID);
}
- (void)testTwoAppsCreateTwoComponents {
NSString *appName = [self generatedTestAppName];
[FIRApp configureWithName:appName options:[self fakeOptions]];
FIRApp *app = [FIRApp appNamed:appName];
[FIRApp configureWithOptions:[self fakeOptions]];
FIRApp *defaultApp = [FIRApp defaultApp];
XCTAssertNotNil(defaultApp);
XCTAssertNotEqualObjects(app, defaultApp);
id<FIRRemoteConfigProvider> provider = FIR_COMPONENT(FIRRemoteConfigProvider, app.container);
id<FIRRemoteConfigInterop> interop = FIR_COMPONENT(FIRRemoteConfigInterop, app.container);
id<FIRRemoteConfigProvider> defaultAppProvider =
FIR_COMPONENT(FIRRemoteConfigProvider, defaultApp.container);
id<FIRRemoteConfigInterop> defaultAppInterop =
FIR_COMPONENT(FIRRemoteConfigInterop, defaultApp.container);
id providerID = provider;
id interopID = interop;
id defaultAppProviderID = defaultAppProvider;
id defaultAppInteropID = defaultAppInterop;
XCTAssertEqualObjects(providerID, interopID);
XCTAssertEqualObjects(defaultAppProviderID, defaultAppInteropID);
// Check two apps get their own component to register
XCTAssertNotEqualObjects(interopID, defaultAppInteropID);
2019-08-21 14:26:41 -07:00
}
- (void)testThrowsWithEmptyGoogleAppID {
FIROptions *options = [self fakeOptions];
options.googleAppID = @"";
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
2019-08-21 14:26:41 -07:00
// Creating a Remote Config instance should fail since the googleAppID is empty.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
}
- (void)testThrowsWithNilGoogleAppID {
FIROptions *options = [self fakeOptions];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
options.googleAppID = nil;
#pragma clang diagnostic pop
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
2019-08-21 14:26:41 -07:00
// Creating a Remote Config instance should fail since the googleAppID is nil.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
}
- (void)testThrowsWithEmptyGCMSenderID {
FIROptions *options = [self fakeOptions];
options.GCMSenderID = @"";
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
2019-08-21 14:26:41 -07:00
// Creating a Remote Config instance should fail since the GCMSenderID is empty.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
}
- (void)testThrowsWithNilGCMSenderID {
FIROptions *options = [self fakeOptions];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
options.GCMSenderID = nil;
#pragma clang diagnostic pop
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
2019-08-21 14:26:41 -07:00
// Creating a Remote Config instance should fail since the GCMSenderID is nil.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
}
- (void)testThrowsWithEmptyProjectID {
FIROptions *options = [self fakeOptions];
options.projectID = @"";
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
// Creating a Remote Config instance should fail since the projectID is empty.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
}
- (void)testThrowsWithNilProjectID {
FIROptions *options = [self fakeOptions];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
options.projectID = nil;
#pragma clang diagnostic pop
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIRApp *app = [self retainedAppWithName:appName options:options];
FIRRemoteConfigComponent *component = [[FIRRemoteConfigComponent alloc] initWithApp:app];
// Guard against the weakly-held app being deallocated, which would also cause a throw.
XCTAssertNotNil(component.app);
// Creating a Remote Config instance should fail since the projectID is empty.
XCTAssertThrows([component remoteConfigForNamespace:@"some_namespace"]);
2019-08-21 14:26:41 -07:00
}
#pragma mark - Helpers
- (FIROptions *)fakeOptions {
FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"1:123:ios:123abc"
GCMSenderID:@"correct_gcm_sender_id"];
options.APIKey = @"AIzaSy-ApiKeyWithValidFormat_0123456789";
options.projectID = @"project-id";
return options;
2019-08-21 14:26:41 -07:00
}
/// Creates an app that is retained for the duration of the test.
- (FIRApp *)retainedAppWithName:(NSString *)name options:(FIROptions *)options {
FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options];
[_apps addObject:app];
return app;
}
2019-08-21 14:26:41 -07:00
- (NSString *)generatedTestAppName {
return [RCNTestUtilities generatedTestAppNameForTest:self.name];
}
- (FIRRemoteConfigComponent *)providerForTest {
// Create the provider to vend Remote Config instances.
NSString *appName = [self generatedTestAppName];
FIROptions *options = [[self fakeOptions] copy];
FIRApp *app = [self retainedAppWithName:appName options:options];
2019-08-21 14:26:41 -07:00
FIRRemoteConfigComponent *provider = [[FIRRemoteConfigComponent alloc] initWithApp:app];
XCTAssertNotNil(provider);
XCTAssert(provider.app.options.googleAppID.length != 0);
XCTAssert(provider.app.options.GCMSenderID.length != 0);
return provider;
}
@end