FPRUIViewControllerInstrumentTest.m 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2020 Google LLC
  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. #pragma mark - Unswizzle based tests
  15. #if !SWIFT_PACKAGE
  16. #import "FirebasePerformance/Sources/Instrumentation/UIKit/FPRUIViewControllerInstrument.h"
  17. #import <XCTest/XCTest.h>
  18. #import <OCMock/OCMock.h>
  19. #import "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker+Private.h"
  20. #import "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h"
  21. #import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
  22. #import <GoogleUtilities/GULSwizzler.h>
  23. static BOOL originalViewDidAppearInvoked = NO;
  24. static BOOL originalViewDidDisappearInvoked = NO;
  25. @interface FPRUIViewControllerInstrumentTest : XCTestCase
  26. @end
  27. @implementation FPRUIViewControllerInstrumentTest
  28. + (void)setUp {
  29. [super setUp];
  30. FIRPerformance *performance = [FIRPerformance sharedInstance];
  31. [performance setDataCollectionEnabled:YES];
  32. }
  33. + (void)tearDown {
  34. [super tearDown];
  35. FIRPerformance *performance = [FIRPerformance sharedInstance];
  36. [performance setDataCollectionEnabled:NO];
  37. }
  38. - (void)setUp {
  39. [super setUp];
  40. originalViewDidAppearInvoked = NO;
  41. originalViewDidDisappearInvoked = NO;
  42. }
  43. /** Tests that the viewControllerDidAppear: of the FPRScreenTraceTracker sharedInstance is invoked
  44. * when a UIViewController's viewDidAppear: is invoked.
  45. */
  46. - (void)testViewDidAppearInvokesViewControllerDidAppearOnScreenTraceTracker {
  47. UIViewController *testViewController = [[UIViewController alloc] init];
  48. [[UIApplication sharedApplication].keyWindow addSubview:[testViewController view]];
  49. FPRUIViewControllerInstrument *instrument = [[FPRUIViewControllerInstrument alloc] init];
  50. [instrument registerInstrumentors];
  51. // Partial mock isa swizzles the object and we can listen to whether it received certain messages.
  52. id screenTraceTrackerListener = OCMPartialMock([FPRScreenTraceTracker sharedInstance]);
  53. OCMExpect([screenTraceTrackerListener viewControllerDidAppear:testViewController]);
  54. [testViewController viewDidAppear:YES];
  55. OCMVerifyAll(screenTraceTrackerListener);
  56. [screenTraceTrackerListener stopMocking];
  57. [instrument deregisterInstrumentors];
  58. [[testViewController view] removeFromSuperview];
  59. }
  60. /** Tests that the viewControllerDidAppear: of the FPRScreenTraceTracker sharedInstance is invoked
  61. * when a UIViewController's viewDidAppear: is invoked.
  62. */
  63. - (void)testViewDidAppearDoesntInvokeViewControllerDidAppearOnNonKeyWindowView {
  64. UIViewController *testViewController = [[UIViewController alloc] init];
  65. FPRUIViewControllerInstrument *instrument = [[FPRUIViewControllerInstrument alloc] init];
  66. [instrument registerInstrumentors];
  67. // Partial mock isa swizzles the object and we can listen to whether it received certain messages.
  68. id screenTraceTrackerListener = OCMPartialMock([FPRScreenTraceTracker sharedInstance]);
  69. OCMReject([screenTraceTrackerListener viewControllerDidAppear:testViewController]);
  70. [testViewController viewDidAppear:YES];
  71. OCMVerifyAll(screenTraceTrackerListener);
  72. [screenTraceTrackerListener stopMocking];
  73. [instrument deregisterInstrumentors];
  74. }
  75. /** Tests that the viewControllerDidDisappear: of the FPRScreenTraceTracker sharedInstance is
  76. * invoked when a UIViewController's viewDidDisappear: is invoked.
  77. */
  78. - (void)testViewDidDisappearInvokesViewControllerDidDisappearOnScreenTraceTracker {
  79. UIViewController *testViewController = [[UIViewController alloc] init];
  80. FPRUIViewControllerInstrument *instrument = [[FPRUIViewControllerInstrument alloc] init];
  81. [instrument registerInstrumentors];
  82. // Partial mock isa swizzles the object and we can listen to whether it received certain messages.
  83. id screenTraceTrackerListener = OCMPartialMock([FPRScreenTraceTracker sharedInstance]);
  84. OCMExpect([screenTraceTrackerListener viewControllerDidDisappear:testViewController]);
  85. [testViewController viewDidDisappear:YES];
  86. OCMVerifyAll(screenTraceTrackerListener);
  87. [screenTraceTrackerListener stopMocking];
  88. [instrument deregisterInstrumentors];
  89. }
  90. /** Tests that the instrument invokes the IMP that was previously in place for
  91. * [uiViewControllerInstance viewDidAppear:].
  92. */
  93. - (void)testViewDidAppearInvokesPreviousViewDidAppear {
  94. __block BOOL previousViewDidAppearCalled = NO;
  95. Class viewControllerClass = [UIViewController class];
  96. SEL viewDidAppearSelector = @selector(viewDidAppear:);
  97. [GULSwizzler swizzleClass:viewControllerClass
  98. selector:viewDidAppearSelector
  99. isClassSelector:NO
  100. withBlock:^void(id _self, BOOL animated) {
  101. previousViewDidAppearCalled = YES;
  102. }];
  103. UIViewController *testViewController = [[UIViewController alloc] init];
  104. FPRUIViewControllerInstrument *instrument = [[FPRUIViewControllerInstrument alloc] init];
  105. [instrument registerInstrumentors];
  106. XCTAssertFalse(previousViewDidAppearCalled);
  107. [testViewController viewDidAppear:YES];
  108. XCTAssertTrue(previousViewDidAppearCalled);
  109. // This should revert the first IMP that was swizzled as well.
  110. [instrument deregisterInstrumentors];
  111. }
  112. /** Tests that the instrument invokes the IMP that was previously in place for
  113. * [uiViewControllerInstance viewDidDisappear:].
  114. */
  115. - (void)testViewDidAppearInvokesPreviousViewDidDisappear {
  116. __block BOOL previousViewDidDisappearCalled = NO;
  117. Class viewControllerClass = [UIViewController class];
  118. SEL viewDidDisappearSelector = @selector(viewDidDisappear:);
  119. [GULSwizzler swizzleClass:viewControllerClass
  120. selector:viewDidDisappearSelector
  121. isClassSelector:NO
  122. withBlock:^void(id _self, BOOL animated) {
  123. previousViewDidDisappearCalled = YES;
  124. }];
  125. UIViewController *testViewController = [[UIViewController alloc] init];
  126. FPRUIViewControllerInstrument *instrument = [[FPRUIViewControllerInstrument alloc] init];
  127. [instrument registerInstrumentors];
  128. XCTAssertFalse(previousViewDidDisappearCalled);
  129. [testViewController viewDidDisappear:YES];
  130. XCTAssertTrue(previousViewDidDisappearCalled);
  131. // This should revert the first IMP that was swizzled as well.
  132. [instrument deregisterInstrumentors];
  133. }
  134. @end
  135. #endif // SWIFT_PACKAGE