XCUIApplicationProcess+FBQuiescence.m 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. */
  9. #import "XCUIApplicationProcess+FBQuiescence.h"
  10. #import <objc/runtime.h>
  11. #import "FBConfiguration.h"
  12. #import "FBLogger.h"
  13. #import "FBSettings.h"
  14. static void (*original_waitForQuiescenceIncludingAnimationsIdle)(id, SEL, BOOL);
  15. static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, BOOL includingAnimations)
  16. {
  17. NSString *bundleId = [self bundleID];
  18. if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) {
  19. [FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling",
  20. bundleId];
  21. return;
  22. }
  23. NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout;
  24. NSTimeInterval previousTimeout = _XCTApplicationStateTimeout();
  25. _XCTSetApplicationStateTimeout(desiredTimeout);
  26. [FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)",
  27. @(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"];
  28. @try {
  29. original_waitForQuiescenceIncludingAnimationsIdle(self, _cmd, includingAnimations);
  30. } @finally {
  31. _XCTSetApplicationStateTimeout(previousTimeout);
  32. }
  33. }
  34. @implementation XCUIApplicationProcess (FBQuiescence)
  35. #pragma clang diagnostic push
  36. #pragma clang diagnostic ignored "-Wobjc-load-method"
  37. + (void)load
  38. {
  39. Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:));
  40. if (nil != waitForQuiescenceIncludingAnimationsIdleMethod) {
  41. IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdle;
  42. original_waitForQuiescenceIncludingAnimationsIdle = (void (*)(id, SEL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdleMethod, swizzledImp);
  43. } else {
  44. [FBLogger log:@"Could not find method -[XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:]"];
  45. }
  46. }
  47. #pragma clang diagnostic pop
  48. static char XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE;
  49. @dynamic fb_shouldWaitForQuiescence;
  50. - (NSNumber *)fb_shouldWaitForQuiescence
  51. {
  52. id result = objc_getAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE);
  53. if (nil == result) {
  54. return @(YES);
  55. }
  56. return (NSNumber *)result;
  57. }
  58. - (void)setFb_shouldWaitForQuiescence:(NSNumber *)value
  59. {
  60. objc_setAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  61. }
  62. @end