From 28d79788ecd17ea6875dda56aba8df5c3ccd088e Mon Sep 17 00:00:00 2001 From: Sho Ikeda Date: Wed, 6 May 2020 14:51:41 +0900 Subject: [PATCH 1/2] Stop using method swizzling for registering CurrentTestCaseTracker to XCTestObservationCenter The weird workaround is no longer needed in recent Xcode versions (at least Xcode 10.1 or later). --- .../XCTestObservationCenter+Register.m | 77 +------------------ 1 file changed, 3 insertions(+), 74 deletions(-) diff --git a/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m index fa5030a70..8cf733491 100644 --- a/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m +++ b/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -1,5 +1,4 @@ #import -#import #if __has_include("Nimble-Swift.h") #import "Nimble-Swift.h" @@ -7,77 +6,7 @@ #import #endif -#pragma mark - Method Swizzling - -/// Swaps the implementations between two instance methods. -/// -/// @param class The class containing `originalSelector`. -/// @param originalSelector Original method to replace. -/// @param replacementSelector Replacement method. -void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method replacementMethod = class_getInstanceMethod(class, replacementSelector); - - BOOL didAddMethod = - class_addMethod(class, - originalSelector, - method_getImplementation(replacementMethod), - method_getTypeEncoding(replacementMethod)); - - if (didAddMethod) { - class_replaceMethod(class, - replacementSelector, - method_getImplementation(originalMethod), - method_getTypeEncoding(originalMethod)); - } else { - method_exchangeImplementations(originalMethod, replacementMethod); - } -} - -#pragma mark - Private - -@interface XCTestObservationCenter (Private) -- (void)_addLegacyTestObserver:(id)observer; -@end - -@implementation XCTestObservationCenter (Register) - -/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary -/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early -/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. -/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, -/// falling back to registering after the first normal observer if this private method ever changes. -+ (void)load { - if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { - // Swizzle -_addLegacyTestObserver: - swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); - } else { - // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented - swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); - } +__attribute__((constructor)) +static void registerCurrentTestCaseTracker(void) { + [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:[CurrentTestCaseTracker sharedInstance]]; } - -#pragma mark - Replacement Methods - -/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. -- (void)NMB_original__addLegacyTestObserver:(id)observer { - [self NMB_original__addLegacyTestObserver:observer]; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; - }); -} - -/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. -/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) -- (void)NMB_original_addTestObserver:(id)observer { - [self NMB_original_addTestObserver:observer]; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; - }); -} - -@end From 41735f46246b2ab6ad2ef146922b94c19f0224cc Mon Sep 17 00:00:00 2001 From: Sho Ikeda Date: Mon, 11 May 2020 21:58:11 +0900 Subject: [PATCH 2/2] Update CI configuration --- .github/workflows/ci.yml | 4 ++-- .travis.yml | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc14f3e65..e0568acab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: xcode: [11, 11.1, 11.2] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - run: sudo xcode-select -s '/Applications/Xcode_${{ matrix.xcode }}.app' - run: ./test macos - run: ./test ios @@ -29,6 +29,6 @@ jobs: matrix: xcode: [11, 11.1, 11.2] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - run: sudo xcode-select -s '/Applications/Xcode_${{ matrix.xcode }}.app' - run: ./test swiftpm diff --git a/.travis.yml b/.travis.yml index 2fdcb560e..b3e256021 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ branches: - 8.x-branch language: generic -matrix: +jobs: include: - &cocoapods name: CocoaPods Lint @@ -34,8 +34,6 @@ matrix: - &swiftpm_linux name: SwiftPM / Linux / Swift 4.2.4 os: linux - dist: trusty - sudo: required env: - SWIFT_VERSION=4.2.4 install: @@ -47,9 +45,17 @@ matrix: env: - SWIFT_VERSION=5.0.3 - <<: *swiftpm_linux - name: SwiftPM / Linux / Swift 5.1 Development + name: SwiftPM / Linux / Swift 5.1.5 env: - - SWIFT_VERSION=5.1-DEVELOPMENT-SNAPSHOT-2019-09-05-a + - SWIFT_VERSION=5.1.5 + - <<: *swiftpm_linux + name: SwiftPM / Linux / Swift 5.2.2 + env: + - SWIFT_VERSION=5.2.2 + - <<: *swiftpm_linux + name: SwiftPM / Linux / Swift Development + env: + - SWIFT_VERSION=DEVELOPMENT-SNAPSHOT-2020-04-17-a install: true script: - ./test $TYPE