FIRComponentContainerTest.m 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2018 Google
  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. #import "FIRTestCase.h"
  15. #import <FirebaseCore/FIRAppInternal.h>
  16. #import <FirebaseCore/FIRComponent.h>
  17. #import <FirebaseCore/FIRComponentContainerInternal.h>
  18. #import "FIRTestComponents.h"
  19. /// Internally exposed methods and properties for testing.
  20. @interface FIRComponentContainer (TestInternal)
  21. @property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
  22. @property(nonatomic, strong) NSMutableDictionary<NSString *, id> *cachedInstances;
  23. + (void)registerAsComponentRegistrant:(Class<FIRLibrary>)klass
  24. inSet:(NSMutableSet<Class> *)allRegistrants;
  25. - (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet<Class> *)allRegistrants;
  26. @end
  27. @interface FIRComponentContainer (TestInternalImplementations)
  28. - (instancetype)initWithApp:(FIRApp *)app
  29. components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components;
  30. @end
  31. @implementation FIRComponentContainer (TestInternalImplementations)
  32. - (instancetype)initWithApp:(FIRApp *)app
  33. components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components {
  34. self = [self initWithApp:app registrants:[[NSMutableSet alloc] init]];
  35. if (self) {
  36. self.components = [components mutableCopy];
  37. }
  38. return self;
  39. }
  40. @end
  41. @interface FIRComponentContainerTest : FIRTestCase
  42. @end
  43. @implementation FIRComponentContainerTest
  44. #pragma mark - Registration Tests
  45. - (void)testRegisteringConformingClass {
  46. NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
  47. Class testClass = [FIRTestClass class];
  48. [FIRComponentContainer registerAsComponentRegistrant:testClass inSet:allRegistrants];
  49. XCTAssertTrue([allRegistrants containsObject:testClass]);
  50. }
  51. - (void)testComponentsPopulatedOnInit {
  52. FIRComponentContainer *container = [self containerWithRegistrants:@ [[FIRTestClass class]]];
  53. // Verify that the block is stored.
  54. NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocol));
  55. FIRComponentCreationBlock creationBlock = container.components[protocolName];
  56. OCMExpect(creationBlock);
  57. }
  58. #pragma mark - Caching Tests
  59. - (void)testInstanceCached {
  60. FIRComponentContainer *container = [self containerWithRegistrants:@ [[FIRTestClassCached class]]];
  61. // Fetch an instance for `FIRTestProtocolCached`, then fetch it again to assert it's cached.
  62. id<FIRTestProtocolCached> instance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
  63. XCTAssertNotNil(instance1);
  64. id<FIRTestProtocolCached> instance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
  65. XCTAssertNotNil(instance2);
  66. XCTAssertEqual(instance1, instance2);
  67. }
  68. - (void)testInstanceNotCached {
  69. FIRComponentContainer *container = [self containerWithRegistrants:@ [[FIRTestClass class]]];
  70. // Retrieve an instance from the container, then fetch it again and ensure it's not the same
  71. // instance.
  72. id<FIRTestProtocol> instance1 = FIR_COMPONENT(FIRTestProtocol, container);
  73. XCTAssertNotNil(instance1);
  74. id<FIRTestProtocol> instance2 = FIR_COMPONENT(FIRTestProtocol, container);
  75. XCTAssertNotNil(instance2);
  76. XCTAssertNotEqual(instance1, instance2);
  77. }
  78. - (void)testRemoveAllCachedInstances {
  79. FIRComponentContainer *container =
  80. [self containerWithRegistrants:@ [[FIRTestClass class], [FIRTestClassCached class],
  81. [FIRTestClassEagerCached class]]];
  82. // Retrieve an instance of FIRTestClassCached to ensure it's cached.
  83. id<FIRTestProtocolCached> cachedInstance1 = FIR_COMPONENT(FIRTestProtocolCached, container);
  84. id<FIRTestProtocolEagerCached> eagerInstance1 =
  85. FIR_COMPONENT(FIRTestProtocolEagerCached, container);
  86. // FIRTestClassEagerCached and FIRTestClassCached instances should be cached at this point.
  87. XCTAssertTrue(container.cachedInstances.count == 2);
  88. // Remove the instances and verify cachedInstances is empty, and that new instances returned from
  89. // the container don't match the old ones.
  90. [container removeAllCachedInstances];
  91. XCTAssertTrue(container.cachedInstances.count == 0);
  92. id<FIRTestProtocolCached> cachedInstance2 = FIR_COMPONENT(FIRTestProtocolCached, container);
  93. XCTAssertNotEqual(cachedInstance1, cachedInstance2);
  94. id<FIRTestProtocolEagerCached> eagerInstance2 =
  95. FIR_COMPONENT(FIRTestProtocolEagerCached, container);
  96. XCTAssertNotEqual(eagerInstance1, eagerInstance2);
  97. }
  98. #pragma mark - Instantiation Tests
  99. - (void)testEagerInstantiation {
  100. // Create a container with `FIRTestClassEagerCached` as a registrant, which provides the
  101. // implementation for `FIRTestProtocolEagerCached` and requires eager instantiation as well as
  102. // caching so the test can verify it was eagerly instantiated.
  103. FIRComponentContainer *container =
  104. [self containerWithRegistrants:@ [[FIRTestClassEagerCached class]]];
  105. NSString *protocolName = NSStringFromProtocol(@protocol(FIRTestProtocolEagerCached));
  106. XCTAssertNotNil(container.cachedInstances[protocolName]);
  107. }
  108. #pragma mark - Input Validation Tests
  109. - (void)testProtocolAlreadyRegistered {
  110. // Register two classes that provide the same protocol. Only one should be stored, and there
  111. // should be a log stating that the protocol has already been registered. Right now there's no
  112. // guarantee which one will be registered first since it's an NSSet under the hood, but that could
  113. // change in the future.
  114. // TODO(wilsonryan): Assert that the log gets called warning that it's already been registered.
  115. FIRComponentContainer *container =
  116. [self containerWithRegistrants:@ [[FIRTestClass class], [FIRTestClassDuplicate class]]];
  117. XCTAssert(container.components.count == 1);
  118. }
  119. #pragma mark - Convenience Methods
  120. /// Create a container that has registered the test class.
  121. - (FIRComponentContainer *)containerWithRegistrants:(NSArray<Class> *)registrants {
  122. id appMock = OCMClassMock([FIRApp class]);
  123. NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
  124. // Initialize the container with the test classes.
  125. for (Class c in registrants) {
  126. [FIRComponentContainer registerAsComponentRegistrant:c inSet:allRegistrants];
  127. }
  128. return [[FIRComponentContainer alloc] initWithApp:appMock registrants:allRegistrants];
  129. }
  130. @end