FSTEventManagerTests.mm 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright 2017 Google
  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. #import "Firestore/Source/Core/FSTEventManager.h"
  17. #import <OCMock/OCMock.h>
  18. #import <XCTest/XCTest.h>
  19. #import "Firestore/Source/Core/FSTQuery.h"
  20. #import "Firestore/Source/Core/FSTSyncEngine.h"
  21. #import "Firestore/Source/Model/FSTDocumentSet.h"
  22. #import "Firestore/Example/Tests/Util/FSTHelpers.h"
  23. #include "Firestore/core/src/firebase/firestore/model/types.h"
  24. using firebase::firestore::model::OnlineState;
  25. NS_ASSUME_NONNULL_BEGIN
  26. /**
  27. * Converts an OnlineState to an NSNumber, usually for the purpose of adding
  28. * it to an NSArray or similar container. There's no direct conversion from a
  29. * strongly-typed enum to an integral type that could be passed to an NSNumber
  30. * initializer.
  31. */
  32. static NSNumber *ToNSNumber(OnlineState state) {
  33. return @(static_cast<std::underlying_type<OnlineState>::type>(state));
  34. }
  35. // FSTEventManager implements this delegate privately
  36. @interface FSTEventManager () <FSTSyncEngineDelegate>
  37. @end
  38. @interface FSTEventManagerTests : XCTestCase
  39. @end
  40. @implementation FSTEventManagerTests
  41. - (FSTQueryListener *)noopListenerForQuery:(FSTQuery *)query {
  42. return [[FSTQueryListener alloc]
  43. initWithQuery:query
  44. options:[FSTListenOptions defaultOptions]
  45. viewSnapshotHandler:^(FSTViewSnapshot *_Nullable snapshot, NSError *_Nullable error){
  46. }];
  47. }
  48. - (void)testHandlesManyListenersPerQuery {
  49. FSTQuery *query = FSTTestQuery("foo/bar");
  50. FSTQueryListener *listener1 = [self noopListenerForQuery:query];
  51. FSTQueryListener *listener2 = [self noopListenerForQuery:query];
  52. FSTSyncEngine *syncEngineMock = OCMStrictClassMock([FSTSyncEngine class]);
  53. OCMExpect([syncEngineMock setSyncEngineDelegate:[OCMArg any]]);
  54. FSTEventManager *eventManager = [FSTEventManager eventManagerWithSyncEngine:syncEngineMock];
  55. OCMExpect([syncEngineMock listenToQuery:query]);
  56. [eventManager addListener:listener1];
  57. OCMVerifyAll((id)syncEngineMock);
  58. [eventManager addListener:listener2];
  59. [eventManager removeListener:listener2];
  60. OCMExpect([syncEngineMock stopListeningToQuery:query]);
  61. [eventManager removeListener:listener1];
  62. OCMVerifyAll((id)syncEngineMock);
  63. }
  64. - (void)testHandlesUnlistenOnUnknownListenerGracefully {
  65. FSTQuery *query = FSTTestQuery("foo/bar");
  66. FSTQueryListener *listener = [self noopListenerForQuery:query];
  67. FSTSyncEngine *syncEngineMock = OCMStrictClassMock([FSTSyncEngine class]);
  68. OCMExpect([syncEngineMock setSyncEngineDelegate:[OCMArg any]]);
  69. FSTEventManager *eventManager = [FSTEventManager eventManagerWithSyncEngine:syncEngineMock];
  70. [eventManager removeListener:listener];
  71. OCMVerifyAll((id)syncEngineMock);
  72. }
  73. - (FSTQueryListener *)makeMockListenerForQuery:(FSTQuery *)query
  74. viewSnapshotHandler:(void (^)())handler {
  75. FSTQueryListener *listener = OCMClassMock([FSTQueryListener class]);
  76. OCMStub([listener query]).andReturn(query);
  77. OCMStub([listener queryDidChangeViewSnapshot:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
  78. handler();
  79. });
  80. return listener;
  81. }
  82. - (void)testNotifiesListenersInTheRightOrder {
  83. FSTQuery *query1 = FSTTestQuery("foo/bar");
  84. FSTQuery *query2 = FSTTestQuery("bar/baz");
  85. NSMutableArray *eventOrder = [NSMutableArray array];
  86. FSTQueryListener *listener1 = [self makeMockListenerForQuery:query1
  87. viewSnapshotHandler:^{
  88. [eventOrder addObject:@"listener1"];
  89. }];
  90. FSTQueryListener *listener2 = [self makeMockListenerForQuery:query2
  91. viewSnapshotHandler:^{
  92. [eventOrder addObject:@"listener2"];
  93. }];
  94. FSTQueryListener *listener3 = [self makeMockListenerForQuery:query1
  95. viewSnapshotHandler:^{
  96. [eventOrder addObject:@"listener3"];
  97. }];
  98. FSTSyncEngine *syncEngineMock = OCMClassMock([FSTSyncEngine class]);
  99. FSTEventManager *eventManager = [FSTEventManager eventManagerWithSyncEngine:syncEngineMock];
  100. [eventManager addListener:listener1];
  101. [eventManager addListener:listener2];
  102. [eventManager addListener:listener3];
  103. OCMVerify([syncEngineMock listenToQuery:query1]);
  104. OCMVerify([syncEngineMock listenToQuery:query2]);
  105. FSTViewSnapshot *snapshot1 = OCMClassMock([FSTViewSnapshot class]);
  106. OCMStub([snapshot1 query]).andReturn(query1);
  107. FSTViewSnapshot *snapshot2 = OCMClassMock([FSTViewSnapshot class]);
  108. OCMStub([snapshot2 query]).andReturn(query2);
  109. [eventManager handleViewSnapshots:@[ snapshot1, snapshot2 ]];
  110. NSArray *expected = @[ @"listener1", @"listener3", @"listener2" ];
  111. XCTAssertEqualObjects(eventOrder, expected);
  112. }
  113. - (void)testWillForwardOnlineStateChanges {
  114. FSTQuery *query = FSTTestQuery("foo/bar");
  115. FSTQueryListener *fakeListener = OCMClassMock([FSTQueryListener class]);
  116. NSMutableArray *events = [NSMutableArray array];
  117. OCMStub([fakeListener query]).andReturn(query);
  118. OCMStub([fakeListener applyChangedOnlineState:OnlineState::Unknown])
  119. .andDo(^(NSInvocation *invocation) {
  120. [events addObject:ToNSNumber(OnlineState::Unknown)];
  121. });
  122. OCMStub([fakeListener applyChangedOnlineState:OnlineState::Online])
  123. .andDo(^(NSInvocation *invocation) {
  124. [events addObject:ToNSNumber(OnlineState::Online)];
  125. });
  126. FSTSyncEngine *syncEngineMock = OCMClassMock([FSTSyncEngine class]);
  127. OCMExpect([syncEngineMock setSyncEngineDelegate:[OCMArg any]]);
  128. FSTEventManager *eventManager = [FSTEventManager eventManagerWithSyncEngine:syncEngineMock];
  129. [eventManager addListener:fakeListener];
  130. XCTAssertEqualObjects(events, @[ ToNSNumber(OnlineState::Unknown) ]);
  131. [eventManager applyChangedOnlineState:OnlineState::Online];
  132. XCTAssertEqualObjects(events,
  133. (@[ ToNSNumber(OnlineState::Unknown), ToNSNumber(OnlineState::Online) ]));
  134. }
  135. @end
  136. NS_ASSUME_NONNULL_END