aboutsummaryrefslogtreecommitdiffhomepage
path: root/Example/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Example/Core')
-rw-r--r--Example/Core/Tests/FIRComponentContainerTest.m157
-rw-r--r--Example/Core/Tests/FIRComponentTypeTest.m60
-rw-r--r--Example/Core/Tests/FIRTestComponents.h63
-rw-r--r--Example/Core/Tests/FIRTestComponents.m118
4 files changed, 398 insertions, 0 deletions
diff --git a/Example/Core/Tests/FIRComponentContainerTest.m b/Example/Core/Tests/FIRComponentContainerTest.m
new file mode 100644
index 0000000..b255973
--- /dev/null
+++ b/Example/Core/Tests/FIRComponentContainerTest.m
@@ -0,0 +1,157 @@
+// Copyright 2018 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 "FIRTestCase.h"
+
+#import <FirebaseCore/FIRAppInternal.h>
+#import <FirebaseCore/FIRComponent.h>
+#import <FirebaseCore/FIRComponentContainerInternal.h>
+
+#import "FIRTestComponents.h"
+
+/// Internally exposed methods and properties for testing.
+@interface FIRComponentContainer (TestInternal)
+
+@property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
+@property(nonatomic, strong) NSMutableDictionary<NSString *, id> *cachedInstances;
+
++ (void)registerAsComponentRegistrant:(Class)klass inSet:(NSMutableSet<Class> *)allRegistrants;
+
+- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet<Class> *)allRegistrants;
+
+@end
+
+@interface FIRComponentContainerTest : FIRTestCase
+
+@end
+
+@implementation FIRComponentContainerTest
+
+#pragma mark - Registration Tests
+
+- (void)testRegisteringConformingClass {
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+ Class testClass = [FIRTestClass class];
+ [FIRComponentContainer registerAsComponentRegistrant:testClass inSet:allRegistrants];
+ XCTAssertTrue([allRegistrants containsObject:testClass]);
+}
+
+- (void)testRegisteringNonConformingClass {
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+ XCTAssertThrows(
+ [FIRComponentContainer registerAsComponentRegistrant:[NSString class] inSet:allRegistrants]);
+ XCTAssertTrue(allRegistrants.count == 0);
+}
+
+- (void)testComponentsPopulatedOnInit {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[ [FIRTestClass class] ]];
+
+ // Verify that the block is stored.
+ NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocol));
+ FIRComponentCreationBlock creationBlock = container.components[protocolName];
+ OCMExpect(creationBlock);
+}
+
+#pragma mark - Caching Tests
+
+- (void)testInstanceCached {
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClassCached class] ]];
+
+ // Fetch an instance for `FIRTestProtocolCached`, then fetch it again to assert it's cached.
+ id<FIRTestProtocolCached> instance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotNil(instance1);
+ id<FIRTestProtocolCached> instance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotNil(instance2);
+ XCTAssertEqual(instance1, instance2);
+}
+
+- (void)testInstanceNotCached {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[ [FIRTestClass class] ]];
+
+ // Retrieve an instance from the container, then fetch it again and ensure it's not the same
+ // instance.
+ id<FIRTestProtocol> instance1 = FIR_COMPONENT(FIRTestProtocol, container);
+ XCTAssertNotNil(instance1);
+ id<FIRTestProtocol> instance2 = FIR_COMPONENT(FIRTestProtocol, container);
+ XCTAssertNotNil(instance2);
+ XCTAssertNotEqual(instance1, instance2);
+}
+
+- (void)testRemoveAllCachedInstances {
+ FIRComponentContainer *container = [self containerWithRegistrants:@[
+ [FIRTestClass class], [FIRTestClassCached class], [FIRTestClassEagerCached class]
+ ]];
+
+ // Retrieve an instance of FIRTestClassCached to ensure it's cached.
+ id<FIRTestProtocolCached> cachedInstance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ id<FIRTestProtocolEagerCached> eagerInstance1 =
+ FIR_COMPONENT(FIRTestProtocolEagerCached, container);
+
+ // FIRTestClassEagerCached and FIRTestClassCached instances should be cached at this point.
+ XCTAssertTrue(container.cachedInstances.count == 2);
+
+ // Remove the instances and verify cachedInstances is empty, and that new instances returned from
+ // the container don't match the old ones.
+ [container removeAllCachedInstances];
+ XCTAssertTrue(container.cachedInstances.count == 0);
+
+ id<FIRTestProtocolCached> cachedInstance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
+ XCTAssertNotEqual(cachedInstance1, cachedInstance2);
+ id<FIRTestProtocolEagerCached> eagerInstance2 =
+ FIR_COMPONENT(FIRTestProtocolEagerCached, container);
+ XCTAssertNotEqual(eagerInstance1, eagerInstance2);
+}
+
+#pragma mark - Instantiation Tests
+
+- (void)testEagerInstantiation {
+ // Create a container with `FIRTestClassEagerCached` as a registrant, which provides the
+ // implementation for `FIRTestProtocolEagerCached` and requires eager instantiation as well as
+ // caching so the test can verify it was eagerly instantiated.
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClassEagerCached class] ]];
+ NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocolEagerCached));
+ XCTAssertNotNil(container.cachedInstances[protocolName]);
+}
+
+#pragma mark - Input Validation Tests
+
+- (void)testProtocolAlreadyRegistered {
+ // Register two classes that provide the same protocol. Only one should be stored, and there
+ // should be a log stating that the protocol has already been registered. Right now there's no
+ // guarantee which one will be registered first since it's an NSSet under the hood, but that could
+ // change in the future.
+ // TODO(wilsonryan): Assert that the log gets called warning that it's already been registered.
+ FIRComponentContainer *container =
+ [self containerWithRegistrants:@[ [FIRTestClass class], [FIRTestClassDuplicate class] ]];
+ XCTAssert(container.components.count == 1);
+}
+
+#pragma mark - Convenience Methods
+
+/// Create a container that has registered the test class.
+- (FIRComponentContainer *)containerWithRegistrants:(NSArray<Class> *)registrants {
+ id appMock = OCMClassMock([FIRApp class]);
+ NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
+
+ // Initialize the container with the test classes.
+ for (Class c in registrants) {
+ [FIRComponentContainer registerAsComponentRegistrant:c inSet:allRegistrants];
+ }
+
+ return [[FIRComponentContainer alloc] initWithApp:appMock registrants:allRegistrants];
+}
+
+@end
diff --git a/Example/Core/Tests/FIRComponentTypeTest.m b/Example/Core/Tests/FIRComponentTypeTest.m
new file mode 100644
index 0000000..7076fdd
--- /dev/null
+++ b/Example/Core/Tests/FIRComponentTypeTest.m
@@ -0,0 +1,60 @@
+// Copyright 2018 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 "FIRTestCase.h"
+
+#import <FirebaseCore/FIRComponentContainerInternal.h>
+#import <FirebaseCore/FIRComponentType.h>
+
+#import "FIRTestComponents.h"
+
+@interface FIRComponentTypeTest : FIRTestCase
+
+@property(nonatomic, strong) id componentContainerMock;
+@end
+
+@implementation FIRComponentTypeTest
+
+- (void)setUp {
+ [super setUp];
+ _componentContainerMock = OCMClassMock([FIRComponentContainer class]);
+}
+
+- (void)tearDown {
+ [super tearDown];
+ [_componentContainerMock stopMocking];
+}
+
+- (void)testForwardsCallToContainer {
+ Protocol *testProtocol = @protocol(FIRTestProtocol);
+ OCMExpect([self.componentContainerMock instanceForProtocol:testProtocol]);
+
+ // Grab an instance from the container, through ComponentType.
+ __unused id<FIRTestProtocol> instance =
+ [FIRComponentType<id<FIRTestProtocol>> instanceForProtocol:@protocol(FIRTestProtocol)
+ inContainer:self.componentContainerMock];
+ OCMVerifyAll(self.componentContainerMock);
+}
+
+- (void)testMacroForwardsCallToContainer {
+ Protocol *testProtocol = @protocol(FIRTestProtocol);
+ OCMExpect([self.componentContainerMock instanceForProtocol:testProtocol]);
+
+ // Grab an instance from the container, through the macro that uses FIRComponentType.
+ __unused id<FIRTestProtocol> instance =
+ FIR_COMPONENT(FIRTestProtocol, self.componentContainerMock);
+
+ OCMVerifyAll(self.componentContainerMock);
+}
+@end
diff --git a/Example/Core/Tests/FIRTestComponents.h b/Example/Core/Tests/FIRTestComponents.h
new file mode 100644
index 0000000..63b2075
--- /dev/null
+++ b/Example/Core/Tests/FIRTestComponents.h
@@ -0,0 +1,63 @@
+// Copyright 2018 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 <Foundation/Foundation.h>
+
+#import <FirebaseCore/FIRComponent.h>
+#import <FirebaseCore/FIRComponentContainer.h>
+#import <FirebaseCore/FIRComponentRegistrant.h>
+
+@protocol FIRComponentRegistrant;
+
+#pragma mark - Standard Component
+
+/// A test protocol to be used for container testing.
+@protocol FIRTestProtocol
+- (void)doSomething;
+@end
+
+/// A test class that is a component registrant.
+@interface FIRTestClass
+ : NSObject <FIRTestProtocol, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
+@end
+
+/// A test class that is a component registrant, a duplicate of FIRTestClass.
+@interface FIRTestClassDuplicate
+ : NSObject <FIRTestProtocol, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
+@end
+
+#pragma mark - Eager Component
+
+/// A test protocol to be used for container testing.
+@protocol FIRTestProtocolEagerCached
+- (void)doSomethingFaster;
+@end
+
+/// A test class that is a component registrant that provides a component requiring eager
+/// instantiation, and is cached for easier validation that it was instantiated.
+@interface FIRTestClassEagerCached
+ : NSObject <FIRTestProtocolEagerCached, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
+@end
+
+#pragma mark - Cached Component
+
+/// A test protocol to be used for container testing.
+@protocol FIRTestProtocolCached
+@end
+
+/// A test class that is a component registrant that provides a component that requests to be
+/// cached.
+@interface FIRTestClassCached
+ : NSObject <FIRTestProtocolCached, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
+@end
diff --git a/Example/Core/Tests/FIRTestComponents.m b/Example/Core/Tests/FIRTestComponents.m
new file mode 100644
index 0000000..68346f3
--- /dev/null
+++ b/Example/Core/Tests/FIRTestComponents.m
@@ -0,0 +1,118 @@
+// Copyright 2018 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 "FIRTestComponents.h"
+
+#import <FirebaseCore/FIRComponent.h>
+
+#pragma mark - Standard Component
+
+@implementation FIRTestClass
+
+/// FIRTestProtocol conformance.
+- (void)doSomething {
+}
+
+/// FIRComponentRegistrant conformance.
++ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
+ FIRComponent *testComponent =
+ [FIRComponent componentWithProtocol:@protocol(FIRTestProtocol)
+ creationBlock:^id _Nullable(FIRComponentContainer *_Nonnull container,
+ BOOL *_Nonnull isCacheable) {
+ return [[FIRTestClass alloc] init];
+ }];
+ return @[ testComponent ];
+}
+
+/// FIRComponentLifecycleMaintainer conformance.
+- (void)appWillBeDeleted:(FIRApp *)app {
+}
+
+@end
+
+/// A test class that is a component registrant, a duplicate of FIRTestClass.
+@implementation FIRTestClassDuplicate
+
+- (void)doSomething {
+}
+
+/// FIRComponentRegistrant conformance.
++ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
+ FIRComponent *testComponent =
+ [FIRComponent componentWithProtocol:@protocol(FIRTestProtocol)
+ creationBlock:^id _Nullable(FIRComponentContainer *_Nonnull container,
+ BOOL *_Nonnull isCacheable) {
+ return [[FIRTestClassDuplicate alloc] init];
+ }];
+ return @[ testComponent ];
+}
+
+/// FIRComponentLifecycleMaintainer conformance.
+- (void)appWillBeDeleted:(FIRApp *)app {
+}
+
+@end
+
+#pragma mark - Eager Component
+
+@implementation FIRTestClassEagerCached
+
+/// FIRTestProtocolEager conformance.
+- (void)doSomethingFaster {
+}
+
+/// FIRComponentRegistrant conformance.
++ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
+ FIRComponent *testComponent = [FIRComponent
+ componentWithProtocol:@protocol(FIRTestProtocolEagerCached)
+ instantiationTiming:FIRInstantiationTimingAlwaysEager
+ dependencies:@[]
+ creationBlock:^id _Nullable(FIRComponentContainer *_Nonnull container,
+ BOOL *_Nonnull isCacheable) {
+ FIRTestClassEagerCached *instance = [[FIRTestClassEagerCached alloc] init];
+ *isCacheable = YES;
+ [instance doSomethingFaster];
+ return instance;
+ }];
+ return @[ testComponent ];
+}
+
+/// FIRComponentLifecycleMaintainer conformance.
+- (void)appWillBeDeleted:(FIRApp *)app {
+}
+
+@end
+
+#pragma mark - Cached Component
+
+@implementation FIRTestClassCached
+
+/// FIRComponentRegistrant conformance.
++ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
+ FIRComponent *testComponent = [FIRComponent
+ componentWithProtocol:@protocol(FIRTestProtocolCached)
+ creationBlock:^id _Nullable(FIRComponentContainer *_Nonnull container,
+ BOOL *_Nonnull isCacheable) {
+ FIRTestClassCached *instanceToCache = [[FIRTestClassCached alloc] init];
+ *isCacheable = YES;
+ return instanceToCache;
+ }];
+ return @[ testComponent ];
+}
+
+/// FIRComponentLifecycleMaintainer conformance.
+- (void)appWillBeDeleted:(FIRApp *)app {
+}
+
+@end