Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for Xcode 7.3 / Swift 2.2 #244

Merged
merged 6 commits into from
Feb 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Nimble.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@
965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; };
965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; };
965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; };
AEBA64701C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = AEBA646F1C5C5FD10060A057 /* CurrentTestCaseTracker.m */; };
AEBA64711C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = AEBA646F1C5C5FD10060A057 /* CurrentTestCaseTracker.m */; };
AEBA64721C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = AEBA646F1C5C5FD10060A057 /* CurrentTestCaseTracker.m */; };
DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; };
DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; };
DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; };
Expand Down Expand Up @@ -453,6 +456,7 @@
7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAnyOfTest.m; sourceTree = "<group>"; };
965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCUserDescriptionTest.m; sourceTree = "<group>"; };
965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDescriptionTest.swift; sourceTree = "<group>"; };
AEBA646F1C5C5FD10060A057 /* CurrentTestCaseTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CurrentTestCaseTracker.m; sourceTree = "<group>"; };
DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DSL+Wait.swift"; sourceTree = "<group>"; };
DD72EC631A93874A002F7651 /* AllPassTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPassTest.swift; sourceTree = "<group>"; };
DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToObjectTest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -673,6 +677,7 @@
1FD8CD211968AB07008ED995 /* DSL.m */,
1FD8CD221968AB07008ED995 /* NMBExceptionCapture.h */,
1FD8CD231968AB07008ED995 /* NMBExceptionCapture.m */,
AEBA646F1C5C5FD10060A057 /* CurrentTestCaseTracker.m */,
);
path = objc;
sourceTree = "<group>";
Expand Down Expand Up @@ -996,6 +1001,7 @@
1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */,
1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */,
1F43728A1A1B343800EB80F8 /* Functional.swift in Sources */,
AEBA64701C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */,
1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */,
1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */,
1F0FEA9A1AF32DA4001E554E /* ObjCExpectation.swift in Sources */,
Expand Down Expand Up @@ -1106,6 +1112,7 @@
1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */,
1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */,
1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */,
AEBA64721C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */,
1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */,
1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */,
1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */,
Expand Down Expand Up @@ -1190,6 +1197,7 @@
1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */,
1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */,
1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */,
AEBA64711C5C5FD10060A057 /* CurrentTestCaseTracker.m in Sources */,
1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */,
1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */,
1F0FEA9B1AF32DA4001E554E /* ObjCExpectation.swift in Sources */,
Expand Down
36 changes: 34 additions & 2 deletions Sources/Nimble/Adapters/NimbleXCTestHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import XCTest
public class NimbleXCTestHandler : AssertionHandler {
public func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) {
if !assertion {
XCTFail("\(message.stringValue)\n", file: location.file, line: location.line)
recordFailure("\(message.stringValue)\n", location: location)
}
}
}
Expand All @@ -22,7 +22,7 @@ public class NimbleShortXCTestHandler: AssertionHandler {
} else {
msg = "expected \(message.to) \(message.postfixMessage)"
}
XCTFail("\(msg)\n", file: location.file, line: location.line)
recordFailure("\(msg)\n", location: location)
}
}
}
Expand All @@ -35,6 +35,24 @@ class NimbleXCTestUnavailableHandler : AssertionHandler {
}
}

#if _runtime(_ObjC)
/// Helper class providing access to the currently executing XCTestCase instance, if any
@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation {
@objc static let sharedInstance = CurrentTestCaseTracker()

private(set) var currentTestCase: XCTestCase?

@objc func testCaseWillStart(testCase: XCTestCase) {
currentTestCase = testCase
}

@objc func testCaseDidFinish(testCase: XCTestCase) {
currentTestCase = nil
}
}
#endif


func isXCTestAvailable() -> Bool {
#if _runtime(_ObjC)
// XCTest is weakly linked and so may not be present
Expand All @@ -43,3 +61,17 @@ func isXCTestAvailable() -> Bool {
return true
#endif
}

private func recordFailure(message: String, location: SourceLocation) {
#if _runtime(_ObjC)
if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase {
testCase.recordFailureWithDescription(message, inFile: location.file, atLine: location.line, expected: true)
} else {
let msg = "Attempted to report a test failure to XCTest while no test case was running. " +
"The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)"
NSException(name: NSInternalInconsistencyException, reason: msg, userInfo: nil).raise()
}
#else
XCTFail("\(message)\n", file: location.file, line: location.line)
#endif
}
8 changes: 4 additions & 4 deletions Sources/Nimble/DSL+Wait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private enum ErrorResult {
internal class NMBWait: NSObject {
internal class func until(
timeout timeout: NSTimeInterval,
file: String = __FILE__,
file: FileString = __FILE__,
line: UInt = __LINE__,
action: (() -> Void) -> Void) -> Void {
return throwableUntil(timeout: timeout, file: file, line: line) { (done: () -> Void) throws -> Void in
Expand All @@ -24,7 +24,7 @@ internal class NMBWait: NSObject {
// Using a throwable closure makes this method not objc compatible.
internal class func throwableUntil(
timeout timeout: NSTimeInterval,
file: String = __FILE__,
file: FileString = __FILE__,
line: UInt = __LINE__,
action: (() -> Void) throws -> Void) -> Void {
let awaiter = NimbleEnvironment.activeInstance.awaiter
Expand Down Expand Up @@ -71,7 +71,7 @@ internal class NMBWait: NSObject {
}

@objc(untilFile:line:action:)
internal class func until(file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
internal class func until(file: FileString = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
until(timeout: 1, file: file, line: line, action: action)
}
}
Expand All @@ -87,7 +87,7 @@ internal func blockedRunLoopErrorMessageFor(fnName: String, leeway: NSTimeInterv
///
/// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function
/// is executing. Any attempts to touch the run loop may cause non-deterministic behavior.
public func waitUntil(timeout timeout: NSTimeInterval = 1, file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
public func waitUntil(timeout timeout: NSTimeInterval = 1, file: FileString = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
NMBWait.until(timeout: timeout, file: file, line: line, action: action)
}
#endif
2 changes: 1 addition & 1 deletion Sources/Nimble/DSL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal func nimblePrecondition(
}

@noreturn
internal func internalError(msg: String, file: String = __FILE__, line: UInt = __LINE__) {
internal func internalError(msg: String, file: FileString = __FILE__, line: UInt = __LINE__) {
fatalError(
"Nimble Bug Found: \(msg) at \(file):\(line).\n" +
"Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " +
Expand Down
6 changes: 3 additions & 3 deletions Sources/Nimble/ObjCExpectation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ internal struct ObjCMatcherWrapper : Matcher {
public class NMBExpectation : NSObject {
internal let _actualBlock: () -> NSObject!
internal var _negative: Bool
internal let _file: String
internal let _file: FileString
internal let _line: UInt
internal var _timeout: NSTimeInterval = 1.0

public init(actualBlock: () -> NSObject!, negative: Bool, file: String, line: UInt) {
public init(actualBlock: () -> NSObject!, negative: Bool, file: FileString, line: UInt) {
self._actualBlock = actualBlock
self._negative = negative
self._file = file
Expand Down Expand Up @@ -123,7 +123,7 @@ public class NMBExpectation : NSObject {

public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { return toEventuallyNotWithDescription }

public class func failWithMessage(message: String, file: String, line: UInt) {
public class func failWithMessage(message: String, file: FileString, line: UInt) {
fail(message, location: SourceLocation(file: file, line: line))
}
}
Expand Down
7 changes: 6 additions & 1 deletion Sources/Nimble/Utils/SourceLocation.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import Foundation

// Ideally we would always use `StaticString` as the type for tracking the file name
// that expectations originate from, for consistency with `assert` etc. from the
// stdlib, and because recent versions of the XCTest overlay require `StaticString`
// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we
// have to use `String` instead because StaticString can't be generated from Objective-C
#if _runtime(_ObjC)
public typealias FileString = String
#else
public typealias FileString = StaticString
#endif

public class SourceLocation : NSObject {
public final class SourceLocation : NSObject {
public let file: FileString
public let line: UInt

Expand Down
18 changes: 18 additions & 0 deletions Sources/Nimble/objc/CurrentTestCaseTracker.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import <XCTest/XCTest.h>
#import <Nimble/Nimble-Swift.h>

SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker")
@interface CurrentTestCaseTracker : NSObject <XCTestObservation>
+ (CurrentTestCaseTracker *)sharedInstance;
@end

@interface CurrentTestCaseTracker (Register) @end

@implementation CurrentTestCaseTracker (Register)

+ (void)load {
CurrentTestCaseTracker *tracker = [CurrentTestCaseTracker sharedInstance];
[[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:tracker];
}

@end
11 changes: 7 additions & 4 deletions Sources/NimbleTests/Helpers/utils.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Foundation
import Nimble
@testable import Nimble
import XCTest

func failsWithErrorMessage(messages: [String], file: FileString = __FILE__, line: UInt = __LINE__, preferOriginalSourceLocation: Bool = false, closure: () throws -> Void) {
Expand Down Expand Up @@ -32,12 +32,15 @@ func failsWithErrorMessage(messages: [String], file: FileString = __FILE__, line
}
}

let message: String
if let lastFailure = lastFailure {
let msg = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\""
XCTFail(msg, file: filePath, line: lineNumber)
message = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\""
} else {
XCTFail("expected failure message, but got none", file: filePath, line: lineNumber)
message = "expected failure message, but got none"
}
NimbleAssertionHandler.assert(false,
message: FailureMessage(stringValue: message),
location: SourceLocation(file: filePath, line: lineNumber))
}
}

Expand Down