mirror of
https://github.com/mas-cli/mas
synced 2024-11-22 11:33:13 +00:00
⬆️ Commandant (0.18.0)
This commit is contained in:
parent
3527c3dec3
commit
8ed9d06217
399 changed files with 7720 additions and 6616 deletions
|
@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- 🐛 Fix alignment of 2nd column of list command output #298
|
||||
- ✨ `Makefile` #277
|
||||
- 🐛 Specify desired LD_RUNPATH_SEARCH_PATHS at link-time #310
|
||||
- ⬆️ Commandant (0.17.0) #310
|
||||
- ⬆️ Commandant (0.18.0) #310
|
||||
- ⬆️ Nimble (9.0.0) #310
|
||||
- ⬆️ Quick (3.1.0) #310
|
||||
- 🕊 Swift 5.2 #310
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
github "Carthage/Commandant" "0.17.0"
|
||||
github "Carthage/Commandant" "0.18.0"
|
||||
github "Quick/Nimble" "v9.0.0"
|
||||
github "Quick/Quick" "v3.1.0"
|
||||
|
|
32
Carthage/Checkouts/Commandant/.gitignore
vendored
32
Carthage/Checkouts/Commandant/.gitignore
vendored
|
@ -1,24 +1,22 @@
|
|||
# Xcode
|
||||
#
|
||||
.DS_Store
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
|
||||
Carthage/Build
|
||||
Packages/
|
||||
*.xcuserstate
|
||||
.DS_Store
|
||||
.build/
|
||||
.swiftpm/
|
||||
Carthage/Build
|
||||
DerivedData
|
||||
Packages/
|
||||
build/
|
||||
xcuserdata
|
||||
|
|
2
Carthage/Checkouts/Commandant/.swift-version
vendored
2
Carthage/Checkouts/Commandant/.swift-version
vendored
|
@ -1 +1 @@
|
|||
5.0
|
||||
5.2
|
||||
|
|
20
Carthage/Checkouts/Commandant/.travis.yml
vendored
20
Carthage/Checkouts/Commandant/.travis.yml
vendored
|
@ -9,7 +9,7 @@ aliases:
|
|||
script:
|
||||
- rm .swift-version
|
||||
- gem update cocoapods
|
||||
- pod repo update master
|
||||
- pod setup
|
||||
- pod lib lint --verbose
|
||||
os: osx
|
||||
language: objective-c
|
||||
|
@ -29,7 +29,7 @@ aliases:
|
|||
- &swiftpm_linux
|
||||
<<: *swiftpm
|
||||
sudo: required
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
language: generic
|
||||
install:
|
||||
- eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
|
||||
|
@ -41,20 +41,20 @@ branches:
|
|||
matrix:
|
||||
include:
|
||||
- <<: *xcode
|
||||
name: Xcode 10.2 / Swift 5.0
|
||||
osx_image: xcode10.2
|
||||
env: JOB=Xcode10.2
|
||||
name: Xcode 11.4 / Swift 5.2
|
||||
osx_image: xcode11.4
|
||||
env: JOB=Xcode11.4
|
||||
- <<: *cocoapods
|
||||
name: CocoaPods Lint
|
||||
osx_image: xcode10.2
|
||||
osx_image: xcode11.4
|
||||
- <<: *swiftpm_darwin
|
||||
name: SwiftPM / Swift 5.0
|
||||
osx_image: xcode10.2
|
||||
name: SwiftPM / Swift 5.2
|
||||
osx_image: xcode11.4
|
||||
- <<: *swiftpm_linux
|
||||
name: Linux / Swift 5.0
|
||||
name: Linux / Swift 5.2
|
||||
env:
|
||||
- JOB=Linux
|
||||
- SWIFT_VERSION=5.0
|
||||
- SWIFT_VERSION=5.2
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
github "jspahrsummers/xcconfigs" ~> 0.9
|
||||
github "Quick/Quick" ~> 2.0
|
||||
github "Quick/Nimble" ~> 8.0
|
||||
github "jspahrsummers/xcconfigs" ~> 1.1
|
||||
github "Quick/Quick" ~> 3.1.0
|
||||
github "Quick/Nimble" ~> 9.0
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
github "Quick/Nimble" "v8.0.0"
|
||||
github "Quick/Quick" "v2.0.0"
|
||||
github "jspahrsummers/xcconfigs" "0.9"
|
||||
github "Quick/Nimble" "v9.0.0"
|
||||
github "Quick/Quick" "v3.1.0"
|
||||
github "jspahrsummers/xcconfigs" "1.1"
|
||||
|
|
|
@ -16,17 +16,17 @@ Please replace this with what happened instead.
|
|||
|
||||
List the software versions you're using:
|
||||
|
||||
- Quick: *?.?.?*
|
||||
- Nimble: *?.?.?*
|
||||
- Xcode Version: *?.? (????)* (Open Xcode; In menubar: Xcode > About Xcode)
|
||||
- Swift Version: *?.?* (Open Xcode Preferences; Components > Toolchains. If none, use `Xcode Default`.)
|
||||
- Quick: *?.?.?*
|
||||
- Nimble: *?.?.?*
|
||||
- Xcode Version: *?.? (????)* (Open Xcode; In menubar: Xcode > About Xcode)
|
||||
- Swift Version: *?.?* (Open Xcode Preferences; Components > Toolchains. If none, use `Xcode Default`.)
|
||||
|
||||
Please also mention which package manager you used and its version. Delete the
|
||||
other package managers in this list:
|
||||
|
||||
- Cocoapods: *?.?.?* (Use `pod --version` in Terminal)
|
||||
- Carthage: *?.?* (Use `carthage version` in Terminal)
|
||||
- Swift Package Manager *?.?.? (swiftpm-???)* (Use `swift build --version` in Terminal)
|
||||
- Cocoapods: *?.?.?* (Use `pod --version` in Terminal)
|
||||
- Carthage: *?.?* (Use `carthage version` in Terminal)
|
||||
- Swift Package Manager *?.?.? (swiftpm-???)* (Use `swift build --version` in Terminal)
|
||||
|
||||
### Project that demonstrates the issue
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
The PR should summarize what was changed and why. Here are some questions to
|
||||
help you if you're not sure:
|
||||
|
||||
- What behavior was changed?
|
||||
- What code was refactored / updated to support this change?
|
||||
- What issues are related to this PR? Or why was this change introduced?
|
||||
- What behavior was changed?
|
||||
- What code was refactored / updated to support this change?
|
||||
- What issues are related to this PR? Or why was this change introduced?
|
||||
|
||||
Checklist - While not every PR needs it, new features should consider this list:
|
||||
|
||||
- [ ] Does this have tests?
|
||||
- [ ] Does this have documentation?
|
||||
- [ ] Does this break the public API (Requires major version bump)?
|
||||
- [ ] Is this a new feature (Requires minor version bump)?
|
||||
|
||||
- [ ] Does this have tests?
|
||||
- [ ] Does this have documentation?
|
||||
- [ ] Does this break the public API (Requires major version bump)?
|
||||
- [ ] Is this a new feature (Requires minor version bump)?
|
||||
|
|
15
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/dependabot.yml
vendored
Normal file
15
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
45
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/workflows/ci.yml
vendored
Normal file
45
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
cocoapods:
|
||||
name: CocoaPods Lint
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: bundle install
|
||||
- run: ./test podspec
|
||||
|
||||
xcode:
|
||||
name: Xcode ${{ matrix.xcode }} - ${{ matrix.platform }}
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
xcode: [11.7, 12]
|
||||
platform: [macos, ios, tvos]
|
||||
fail-fast: false
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: ./test ${{ matrix.platform }}
|
||||
- run: ./test ${{ matrix.platform }}_xcodespm
|
||||
|
||||
swiftpm_darwin:
|
||||
name: SwiftPM, Darwin, Xcode ${{ matrix.xcode }}
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
xcode: [11.7, 12]
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: ./test swiftpm
|
15
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/workflows/swiftlint.yml
vendored
Normal file
15
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/workflows/swiftlint.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
name: SwiftLint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/swiftlint.yml'
|
||||
- '.swiftlint.yml'
|
||||
- '**/*.swift'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: norio-nomura/action-swiftlint@3.1.0
|
|
@ -1,2 +0,0 @@
|
|||
swift:
|
||||
config_file: .swiftlint.yml
|
|
@ -1 +0,0 @@
|
|||
4.2
|
|
@ -6,6 +6,7 @@ included:
|
|||
- Tests
|
||||
|
||||
excluded:
|
||||
- Package.swift
|
||||
- Carthage/Checkouts
|
||||
- Tests/NimbleTests/XCTestManifests.swift
|
||||
- Tests/NimbleTests/Helpers/XCTestCaseProvider.swift
|
||||
|
|
|
@ -1,49 +1,40 @@
|
|||
osx_image: xcode10.1
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
language: generic
|
||||
matrix:
|
||||
jobs:
|
||||
include:
|
||||
- os: osx
|
||||
sudo: required
|
||||
env: TYPE=podspec
|
||||
install: bundle install
|
||||
name: CocoaPods Lint
|
||||
- os: osx
|
||||
env: TYPE=ios
|
||||
name: iOS / Swift 4.2.1
|
||||
- os: osx
|
||||
env: TYPE=tvos
|
||||
name: tvOS / Swift 4.2.1
|
||||
- os: osx
|
||||
env: TYPE=macos
|
||||
name: macOS / Swift 4.2.1
|
||||
- os: osx
|
||||
env: TYPE=macos
|
||||
osx_image: xcode10.2
|
||||
name: macOS / Swift 5.0
|
||||
- os: osx
|
||||
env:
|
||||
- TYPE=swiftpm
|
||||
- os: osx
|
||||
env:
|
||||
- TYPE=swiftpm
|
||||
osx_image: xcode10.2
|
||||
- &linux
|
||||
name: Linux / Swift 4.2.1
|
||||
# - &xcode
|
||||
# name: Xcode 10.3 / Swift 5.0
|
||||
# os: osx
|
||||
# osx_image: xcode10.3
|
||||
# script:
|
||||
# - ./test macos
|
||||
# - ./test ios
|
||||
# - ./test tvos
|
||||
# - &swiftpm_darwin
|
||||
# name: SwiftPM / Darwin / Swift 5.0
|
||||
# os: osx
|
||||
# osx_image: xcode10.3
|
||||
# script: ./test swiftpm
|
||||
- &swiftpm_linux
|
||||
name: SwiftPM / Linux / Swift 5.2.5
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
env:
|
||||
- TYPE=swiftpm
|
||||
- SWIFT_VERSION=4.2.1
|
||||
- SWIFT_VERSION=5.2.5
|
||||
install:
|
||||
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"
|
||||
- <<: *linux
|
||||
name: Linux / Swift 5.0 Development
|
||||
- eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
|
||||
script:
|
||||
- ./test swiftpm
|
||||
- <<: *swiftpm_linux
|
||||
name: SwiftPM / Linux / Swift 5.3 Development
|
||||
env:
|
||||
- TYPE=swiftpm
|
||||
- SWIFT_VERSION=5.0-DEVELOPMENT-SNAPSHOT-2019-02-28-a
|
||||
install:
|
||||
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"
|
||||
- SWIFT_VERSION=5.3-DEVELOPMENT-SNAPSHOT-2020-09-04-a
|
||||
- <<: *swiftpm_linux
|
||||
name: SwiftPM / Linux / Swift Development
|
||||
env:
|
||||
- SWIFT_VERSION=DEVELOPMENT-SNAPSHOT-2020-08-31-a
|
||||
install: true
|
||||
script:
|
||||
- ./test $TYPE
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5"
|
||||
github "mattgallagher/CwlCatchException" ~> 2.0
|
||||
github "mattgallagher/CwlPreconditionTesting" ~> 2.0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923"
|
||||
github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5"
|
||||
github "mattgallagher/CwlCatchException" "2.0.0"
|
||||
github "mattgallagher/CwlPreconditionTesting" "2.0.0"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
ISC License
|
||||
|
||||
Copyright © 2017 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
// swift-tools-version:5.0
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "CwlCatchException",
|
||||
products: [
|
||||
.library(name: "CwlCatchException", targets: ["CwlCatchException"]),
|
||||
],
|
||||
targets: [
|
||||
Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]),
|
||||
Target(name: "CwlCatchExceptionSupport")
|
||||
.target(name: "CwlCatchException", dependencies: [.target(name: "CwlCatchExceptionSupport")]),
|
||||
.target(name: "CwlCatchExceptionSupport"),
|
||||
.testTarget(name: "CwlCatchExceptionTests", dependencies: [.target(name: "CwlCatchException")])
|
||||
]
|
||||
)
|
||||
|
|
|
@ -1,46 +1,18 @@
|
|||
# CwlCatchException
|
||||
A simple Swift wrapper around an Objective-C `@try`/`@catch` statement that selectively catches Objective-C exceptions by `NSException` subtype, rethrowing if any caught exception is not the expected subtype.
|
||||
|
||||
Look at [CwlCatchExceptionTests.swift](https://github.com/mattgallagher/CwlCatchException/blob/master/CwlCatchExceptionTests/CwlCatchExceptionTests.swift?ts=4) for syntax.
|
||||
Look at [CwlCatchExceptionTests.swift](https://github.com/mattgallagher/CwlCatchException/blob/master/Tests/CwlCatchExceptionTests/CwlCatchExceptionTests.swift) for syntax.
|
||||
|
||||
## Requirements
|
||||
|
||||
From version 2.0.0-beta.1, building CwlCatchException requires Swift 5 or newer and the Swift Package Manager.
|
||||
|
||||
For use with older versions of Swift or other package managers, [use version 1.2.0 or older](https://github.com/mattgallagher/CwlCatchException/tree/1.2.0).
|
||||
|
||||
## Adding to your project
|
||||
|
||||
This project can be used by direct inclusion in your projects or through any of the Swift Package Manager, CocoaPods or Carthage.
|
||||
|
||||
Minimum requirements are iOS 8 or macOS 10.9.
|
||||
|
||||
### Manual inclusion
|
||||
|
||||
1. In a subdirectory of your project's directory, run `git clone https://github.com/mattgallagher/CwlCatchException.git`
|
||||
2. Drag the "CwlCatchException.xcodeproj" file from the Finder into your own project's file tree in Xcode
|
||||
3. Add the "CwlCatchException.framework" from the "Products" folder of the CwlCatchException project's file tree to the "Copy Files (Frameworks)" build phases of any target that you want to include this module.
|
||||
|
||||
That third step is a little tricky if you're unfamiliar with Xcode but it involves:
|
||||
|
||||
a. click on your project in the file tree
|
||||
b. click on the target to whih you want to add this module
|
||||
c. select the "Build Phases" tab
|
||||
d. if you don't already have a "Copy File" build phase with a "Destination: Frameworks", add one using the "+" button in the top left of the tab
|
||||
e. click the "+" within the "Copy File (Frameworks)" phase and from the list that appears, select the "CwlCatchException.framework" (if there are multiple frameworks with the same name, look for the one that appears *above* the corresponding macOS or iOS CwlCatchException testing target).
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
Add the following to the `dependencies` array in your "Package.swift" file:
|
||||
|
||||
.Package(url: "https://github.com/mattgallagher/CwlCatchException.git", majorVersion: 1),
|
||||
.package(url: "https://github.com/mattgallagher/CwlCatchException.git", from: Version("2.0.0-beta.1"))
|
||||
|
||||
Or, if you're using the `swift-tools-version:4.0` package manager, add the following to the `dependencies` array in your "Package.swift" file:
|
||||
|
||||
.package(url: "https://github.com/mattgallagher/CwlCatchException.git", majorVersion: 1)
|
||||
|
||||
### CocoaPods
|
||||
|
||||
Add the following to your target in your "Podfile":
|
||||
|
||||
pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git'
|
||||
|
||||
### Carthage
|
||||
|
||||
Add the following line to your Cartfile:
|
||||
|
||||
git "https://github.com/mattgallagher/CwlCatchException.git" "master"
|
||||
Or by adding `https://github.com/mattgallagher/CwlCatchException.git`, version 2.0.0-beta.1 or later, to the list of Swift packages for any project in Xcode.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlAssertionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -24,12 +24,12 @@ import Foundation
|
|||
import CwlCatchExceptionSupport
|
||||
#endif
|
||||
|
||||
private func catchReturnTypeConverter<T: NSException>(_ type: T.Type, block: () -> Void) -> T? {
|
||||
private func catchReturnTypeConverter<T: NSException>(_ type: T.Type, block: @escaping () -> Void) -> T? {
|
||||
return catchExceptionOfKind(type, block) as? T
|
||||
}
|
||||
|
||||
extension NSException {
|
||||
public static func catchException(in block: () -> Void) -> Self? {
|
||||
public static func catchException(in block: @escaping () -> Void) -> Self? {
|
||||
return catchReturnTypeConverter(self, block: block)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlAssertionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -20,10 +20,7 @@
|
|||
|
||||
#import "CwlCatchException.h"
|
||||
|
||||
#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
|
||||
__attribute__((visibility("hidden")))
|
||||
#endif
|
||||
NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) {
|
||||
NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void)) {
|
||||
@try {
|
||||
inBlock();
|
||||
} @catch (NSException *exception) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlCatchException
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -20,13 +20,4 @@
|
|||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for CwlCatchException.
|
||||
FOUNDATION_EXPORT double CwlCatchExceptionVersionNumber;
|
||||
|
||||
//! Project version string for CwlCatchException.
|
||||
FOUNDATION_EXPORT const unsigned char CwlCatchExceptionVersionString[];
|
||||
|
||||
#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
|
||||
__attribute__((visibility("hidden")))
|
||||
#endif
|
||||
NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void));
|
||||
NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void));
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
// swift-tools-version:5.0
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "CwlPreconditionTesting",
|
||||
targets: [
|
||||
Target(name: "CwlPreconditionTesting", dependencies: [
|
||||
"CwlMachBadInstructionHandler"
|
||||
]),
|
||||
Target(name: "CwlMachBadInstructionHandler")
|
||||
products: [
|
||||
.library(name: "CwlPreconditionTesting", targets: ["CwlPreconditionTesting", "CwlMachBadInstructionHandler"]),
|
||||
.library(name: "CwlPosixPreconditionTesting", targets: ["CwlPosixPreconditionTesting"])
|
||||
],
|
||||
dependencies: [
|
||||
.Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])),
|
||||
.package(url: "https://github.com/mattgallagher/CwlCatchException.git", from: "2.0.0")
|
||||
],
|
||||
exclude: [
|
||||
"Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h",
|
||||
"Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h",
|
||||
"Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift",
|
||||
targets: [
|
||||
.target(
|
||||
name: "CwlPreconditionTesting",
|
||||
dependencies: [
|
||||
.target(name: "CwlMachBadInstructionHandler"),
|
||||
.product(name: "CwlCatchException")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "CwlPosixPreconditionTesting"
|
||||
),
|
||||
.target(name: "CwlMachBadInstructionHandler"),
|
||||
.testTarget(name: "CwlPreconditionTestingTests", dependencies: ["CwlPreconditionTesting", "CwlPosixPreconditionTesting"])
|
||||
]
|
||||
)
|
||||
|
|
|
@ -8,66 +8,40 @@ For an extended discussion of this code, please see the Cocoa with Love article:
|
|||
|
||||
[Partial functions in Swift, Part 2: Catching precondition failures](http://cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html)
|
||||
|
||||
## Requirements
|
||||
|
||||
From version 2.0.0-beta.1, building CwlPreconditionTesting requires Swift 5 or newer and the Swift Package Manager.
|
||||
|
||||
For use with older versions of Swift or other package managers, [use version 1.2.0 or older](https://github.com/mattgallagher/CwlPreconditionTesting/tree/1.2.0).
|
||||
|
||||
## Adding to your project
|
||||
|
||||
This project can be used by manual inclusion in your projects or through any of the Swift Package Manager, CocoaPods or Carthage.
|
||||
|
||||
Minimum requirements are iOS 8 (simulator-only) or macOS 10.9. The project includes tvOS 9 and POSIX targets but these aren't regularly tested.
|
||||
|
||||
### Manual inclusion
|
||||
|
||||
1. In a subdirectory of your project's directory, run `git clone https://github.com/mattgallagher/CwlPreconditionTesting.git`
|
||||
2. Drag the "CwlPreconditionTesting.xcodeproj" file from the Finder into your own project's file tree in Xcode
|
||||
3. Add the "CwlPreconditionTesting.framework" from the "Products" folder of the CwlPreconditionTesting project's file tree to the "Copy Files (Frameworks)" build phases of any target that you want to include this module.
|
||||
4. Drag the "CwlCatchException.framework" from the "Dependencies" group (within the CwlPreconditionTesting project's file tree) onto the same "Copy Files (Frameworks)" build phase (this item may be red but that shouldn't be a problem).
|
||||
|
||||
That third step is a little tricky if you're unfamiliar with Xcode but it involves:
|
||||
|
||||
a. click on your project in the file tree
|
||||
b. click on the target to whih you want to add this module
|
||||
c. select the "Build Phases" tab
|
||||
d. if you don't already have a "Copy File" build phase with a "Destination: Frameworks", add one using the "+" button in the top left of the tab
|
||||
e. click the "+" within the "Copy File (Frameworks)" phase and from the list that appears, select the "CwlPreconditionTesting.framework" (if there are multiple frameworks with the same name, look for the one that appears *above* the corresponding macOS or iOS CwlPreconditionTesting testing target).
|
||||
|
||||
When building using this approach, the "FetchDependencies" target will use the Swift Package Manager to download the "CwlCatchException" project from github. The download is stored in the "Build intermediates" directory for your project. Normally, you can ignore its existence but if you get any errors from the "FetchDependencies" target, you might need to clean the build folder (Hold "Option" key while selecting "Product" → "Clean Build Folder..." from the Xcode menubar).
|
||||
|
||||
You can use the "Package.swift" to manage the behavior of the Swift Package Manager or if you want to download dependencies manually (instead of using this behind-the-scenes use of the Swift package manager), you should delete the "FetchDependencies" target and replace the "CwlCatchException" targets with alternatives that build the dependencies in accordance with your manual download.
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
Add the following to the `dependencies` array in your "Package.swift" file:
|
||||
|
||||
.Package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", majorVersion: 1),
|
||||
.package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", from: Version("2.0.0-beta.1"))
|
||||
|
||||
Or, if you're using the `swift-tools-version:4.0` package manager, add the following to the `dependencies` array in your "Package.swift" file:
|
||||
Or by adding `https://github.com/mattgallagher/CwlPreconditionTesting.git`, version 2.0.0-beta.1 or later, to the list of Swift packages for any project in Xcode.
|
||||
|
||||
.package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", majorVersion: 1)
|
||||
## Usage
|
||||
|
||||
### CocoaPods
|
||||
On macOS and iOS you can use the regular version:
|
||||
|
||||
Add the following lines to your target in your "Podfile":
|
||||
```swift
|
||||
import CwlPreconditionTesting
|
||||
|
||||
pod 'CwlPreconditionTesting', :git => 'https://github.com/mattgallagher/CwlPreconditionTesting.git'
|
||||
pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git'
|
||||
let e = catchBadInstruction {
|
||||
precondition(false, "THIS PRECONDITION FAILURE IS EXPECTED")
|
||||
}
|
||||
```
|
||||
|
||||
### Carthage
|
||||
on tvOS, Linux and other platforms, you can use the POSIX version:
|
||||
|
||||
Add the following line to your Cartfile:
|
||||
```swift
|
||||
import CwlPosixPreconditionTesting
|
||||
|
||||
git "https://github.com/mattgallagher/CwlPreconditionTesting.git" "master"
|
||||
let e = catchBadInstruction {
|
||||
precondition(false, "THIS PRECONDITION FAILURE IS EXPECTED")
|
||||
}
|
||||
```
|
||||
|
||||
## Using POSIX signals and setjmp/longjmp
|
||||
|
||||
For comparison or for anyone running this code on a platform without Mach exceptions or the Objective-C runtime, I've added a proof-of-concept implementation of `catchBadInstruction` that uses a POSIX SIGILL `sigaction` and `setjmp`/`longjmp` to perform the throw.
|
||||
|
||||
In Xcode, you can simply select the CwlPreconditionTesting_POSIX target (instead of the OSX or iOS targets). If you're building without Xcode: all you need is the CwlCatchBadInstructionPOSIX.swift file (compared to the Mach exception handler, the code is tiny doesn't have any weird Objective-C/MiG file dependencies).
|
||||
|
||||
**Warning No. 1**: on OS X, this approach can't be used when lldb is attached since lldb's Mach exception handler blocks the SIGILL from ever occurring (I've disabled the "Debug Executable" setting for the tests in Xcode - re-enable it to witness the problem).
|
||||
|
||||
**Warning No. 2**: if you're switching between the CwlPreconditionTesting_OSX and CwlPreconditionTesting_POSIX targets, Xcode (as of Xcode 7.2.1) will not detect the change and will not remove the old framework correctly so you'll need to *clean your project* otherwise the old framework will hang around.
|
||||
|
||||
Additional problems in decreasing severity include:
|
||||
|
||||
* the signal handler is whole process (rather than correctly scoped to the thread where the "catch" occurs)
|
||||
* the signal handler doesn't deal with re-entrancy whereas the mach exception handler remains deterministic in the face of multiple fatal errors
|
||||
* the signal handler overwrites the "[red zone](https://en.wikipedia.org/wiki/Red_zone_(computing))" which is technically frowned upon in signal handlers (although unlikely to cause problems here)
|
||||
**Warning**: this POSIX version can't be used when lldb is attached since lldb's Mach exception handler blocks the SIGILL from ever occurring. You should disable the "Debug Executable" setting for the tests in Xcode. The POSIX version of the signal handler is also whole process (rather than correctly scoped to the thread where the "catch" occurs).
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,33 +18,36 @@
|
|||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#ifdef __APPLE__
|
||||
#import "TargetConditionals.h"
|
||||
#if TARGET_OS_OSX || TARGET_OS_IOS
|
||||
|
||||
#import "mach_excServer.h"
|
||||
#import "CwlMachBadInstructionHandler.h"
|
||||
#import "mach_excServer.h"
|
||||
#import "CwlMachBadInstructionHandler.h"
|
||||
|
||||
@protocol BadInstructionReply <NSObject>
|
||||
+(NSNumber *)receiveReply:(NSValue *)value;
|
||||
@end
|
||||
|
||||
/// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state.
|
||||
kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
|
||||
bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt };
|
||||
Class badInstructionClass = NSClassFromString(@"BadInstructionException");
|
||||
NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)];
|
||||
return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue];
|
||||
}
|
||||
|
||||
// The mach port should be configured so that this function is never used.
|
||||
kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) {
|
||||
assert(false);
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
// The mach port should be configured so that this function is never used.
|
||||
kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
|
||||
assert(false);
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
@protocol BadInstructionReply <NSObject>
|
||||
+(NSNumber *)receiveReply:(NSValue *)value;
|
||||
@end
|
||||
|
||||
/// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state.
|
||||
kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
|
||||
bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt };
|
||||
Class badInstructionClass = NSClassFromString(@"BadInstructionException");
|
||||
NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)];
|
||||
return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue];
|
||||
}
|
||||
|
||||
// The mach port should be configured so that this function is never used.
|
||||
kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) {
|
||||
assert(false);
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
// The mach port should be configured so that this function is never used.
|
||||
kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
|
||||
assert(false);
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* TARGET_OS_OSX || TARGET_OS_IOS */
|
||||
#endif /* __APPLE__ */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -19,8 +19,14 @@
|
|||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_OSX || TARGET_OS_IOS
|
||||
|
||||
#import <mach/mach.h>
|
||||
|
||||
extern bool _swift_disableExclusivityChecking;
|
||||
extern bool _swift_reportFatalErrorsToDebugger;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
@ -68,3 +74,5 @@ typedef struct
|
|||
} bad_instruction_exception_reply_t;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
* OPTIONS:
|
||||
*/
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
/* Module mach_exc */
|
||||
|
||||
#define __MIG_check__Request__mach_exc_subsystem__ 1
|
||||
|
||||
#include "mach_excServer.h"
|
||||
#import "mach_excServer.h"
|
||||
#if TARGET_OS_OSX || TARGET_OS_IOS
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
|
@ -534,4 +533,4 @@ mig_external mig_routine_t mach_exc_server_routine
|
|||
return catch_mach_exc_subsystem.routine[msgh_id].stub_routine;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* TARGET_OS_OSX || TARGET_OS_IOS */
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#ifdef __APPLE__
|
||||
#import "TargetConditionals.h"
|
||||
#if TARGET_OS_OSX || TARGET_OS_IOS
|
||||
|
||||
#ifndef _mach_exc_server_
|
||||
#define _mach_exc_server_
|
||||
|
||||
/* Module mach_exc */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
|
@ -319,3 +324,6 @@ __AfterMigServerHeader
|
|||
#endif /* __AfterMigServerHeader */
|
||||
|
||||
#endif /* _mach_exc_server_ */
|
||||
|
||||
#endif /* TARGET_OS_OSX || TARGET_OS_IOS */
|
||||
#endif /* __APPLE__ */
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// CwlCatchBadInstructionPosix.swift
|
||||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 8/02/2016.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#if arch(x86_64)
|
||||
|
||||
import Foundation
|
||||
|
||||
// This file is an alternative implementation to CwlCatchBadInstruction.swift that uses a SIGILL signal action and setenv/longjmp instead of a Mach exception handler and Objective-C exception raising.
|
||||
//
|
||||
// WARNING:
|
||||
// This code is quick and dirty. It's a proof of concept for using a SIGILL handler and setjmp/longjmp where Mach exceptions and the Obj-C runtime aren't available. I ran the automated tests when I first wrote this code but I don't personally use it at all so by the time you're reading this comment, it probably broke and I didn't notice.
|
||||
// Obvious limitations:
|
||||
// * It doesn't work when debugging with lldb.
|
||||
// * It doesn't scope correctly to the thread (it's global)
|
||||
// * In violation of rules for signal handlers, it writes to the "red zone" on the stack
|
||||
// * It isn't re-entrant
|
||||
// * Plus all of the same caveats as the Mach exceptions version (doesn't play well with other handlers, probably leaks ARC memory, etc)
|
||||
// Treat it like a loaded shotgun. Don't point it at your face.
|
||||
|
||||
// This function is called from the signal handler to shut down the thread and return 1 (indicating a SIGILL was received).
|
||||
private func callThreadExit() {
|
||||
pthread_exit(UnsafeMutableRawPointer(bitPattern: 1))
|
||||
}
|
||||
|
||||
// When called, this signal handler simulates a function call to `callThreadExit`
|
||||
private func sigIllHandler(code: Int32, info: UnsafeMutablePointer<__siginfo>?, uap: UnsafeMutableRawPointer?) -> Void {
|
||||
guard let context = uap?.assumingMemoryBound(to: ucontext64_t.self) else { return }
|
||||
|
||||
// 1. Decrement the stack pointer
|
||||
context.pointee.uc_mcontext64.pointee.__ss.__rsp -= __uint64_t(MemoryLayout<Int>.size)
|
||||
|
||||
// 2. Save the old Instruction Pointer to the stack.
|
||||
let rsp = context.pointee.uc_mcontext64.pointee.__ss.__rsp
|
||||
if let ump = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(rsp)) {
|
||||
ump.pointee = rsp
|
||||
}
|
||||
|
||||
// 3. Set the Instruction Pointer to the new function's address
|
||||
var f: @convention(c) () -> Void = callThreadExit
|
||||
withUnsafePointer(to: &f) { $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { ptr in
|
||||
context.pointee.uc_mcontext64.pointee.__ss.__rip = ptr.pointee
|
||||
} }
|
||||
}
|
||||
|
||||
/// Without Mach exceptions or the Objective-C runtime, there's nothing to put in the exception object. It's really just a boolean – either a SIGILL was caught or not.
|
||||
public class BadInstructionException {
|
||||
}
|
||||
|
||||
/// Run the provided block. If a POSIX SIGILL is received, handle it and return a BadInstructionException (which is just an empty object in this POSIX signal version). Otherwise return nil.
|
||||
/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a SIGILL is received, the block will be interrupted using a C `longjmp`. The risks associated with abrupt jumps apply here: most Swift functions are *not* interrupt-safe. Memory may be leaked and the program will not necessarily be left in a safe state.
|
||||
/// - parameter block: a function without parameters that will be run
|
||||
/// - returns: if an SIGILL is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`.
|
||||
public func catchBadInstruction(block: @escaping () -> Void) -> BadInstructionException? {
|
||||
// Construct the signal action
|
||||
var sigActionPrev = sigaction()
|
||||
let action = __sigaction_u(__sa_sigaction: sigIllHandler)
|
||||
var sigActionNew = sigaction(__sigaction_u: action, sa_mask: sigset_t(), sa_flags: SA_SIGINFO)
|
||||
|
||||
// Install the signal action
|
||||
if sigaction(SIGILL, &sigActionNew, &sigActionPrev) != 0 {
|
||||
fatalError("Sigaction error: \(errno)")
|
||||
}
|
||||
|
||||
defer {
|
||||
// Restore the previous signal action
|
||||
if sigaction(SIGILL, &sigActionPrev, nil) != 0 {
|
||||
fatalError("Sigaction error: \(errno)")
|
||||
}
|
||||
}
|
||||
|
||||
var b = block
|
||||
let caught: Bool = withUnsafeMutablePointer(to: &b) { blockPtr in
|
||||
// Run the block on its own thread
|
||||
var handlerThread: pthread_t? = nil
|
||||
let e = pthread_create(&handlerThread, nil, { arg in
|
||||
(arg.assumingMemoryBound(to: (() -> Void).self).pointee)()
|
||||
return nil
|
||||
}, blockPtr)
|
||||
precondition(e == 0, "Unable to create thread")
|
||||
|
||||
// Wait for completion and get the result. It will be either `nil` or bitPattern 1
|
||||
var rawResult: UnsafeMutableRawPointer? = nil
|
||||
let e2 = pthread_join(handlerThread!, &rawResult)
|
||||
precondition(e2 == 0, "Thread join failed")
|
||||
return Int(bitPattern: rawResult) != 0
|
||||
}
|
||||
|
||||
return caught ? BadInstructionException() : nil
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,6 +18,8 @@
|
|||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#if (os(macOS) || os(iOS)) && arch(x86_64)
|
||||
|
||||
import Foundation
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
|
@ -44,46 +46,44 @@ public class BadInstructionException: NSException {
|
|||
/// An Objective-C callable function, invoked from the `mach_exc_server` callback function `catch_mach_exception_raise_state` to push the `raiseBadInstructionException` function onto the stack.
|
||||
@objc(receiveReply:)
|
||||
public class func receiveReply(_ value: NSValue) -> NSNumber {
|
||||
#if arch(x86_64)
|
||||
var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil)
|
||||
withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) }
|
||||
|
||||
let old_state: UnsafePointer<natural_t> = reply.old_state!
|
||||
let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt
|
||||
let new_state: thread_state_t = reply.new_state!
|
||||
let new_stateCnt: UnsafeMutablePointer<mach_msg_type_number_t> = reply.new_stateCnt!
|
||||
|
||||
// Make sure we've been given enough memory
|
||||
if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT {
|
||||
return NSNumber(value: KERN_INVALID_ARGUMENT)
|
||||
}
|
||||
|
||||
// Read the old thread state
|
||||
var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee }
|
||||
|
||||
// 1. Decrement the stack pointer
|
||||
state.__rsp -= __uint64_t(MemoryLayout<Int>.size)
|
||||
|
||||
// 2. Save the old Instruction Pointer to the stack.
|
||||
if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) {
|
||||
pointer.pointee = state.__rip
|
||||
} else {
|
||||
return NSNumber(value: KERN_INVALID_ARGUMENT)
|
||||
}
|
||||
|
||||
// 3. Set the Instruction Pointer to the new function's address
|
||||
var f: @convention(c) () -> Void = raiseBadInstructionException
|
||||
withUnsafePointer(to: &f) {
|
||||
state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee }
|
||||
}
|
||||
|
||||
// Write the new thread state
|
||||
new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state }
|
||||
new_stateCnt.pointee = x86_THREAD_STATE64_COUNT
|
||||
|
||||
return NSNumber(value: KERN_SUCCESS)
|
||||
#else
|
||||
fatalError("Unavailable for this CPU architecture")
|
||||
#endif
|
||||
var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil)
|
||||
withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) }
|
||||
|
||||
let old_state: UnsafePointer<natural_t> = reply.old_state!
|
||||
let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt
|
||||
let new_state: thread_state_t = reply.new_state!
|
||||
let new_stateCnt: UnsafeMutablePointer<mach_msg_type_number_t> = reply.new_stateCnt!
|
||||
|
||||
// Make sure we've been given enough memory
|
||||
if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT {
|
||||
return NSNumber(value: KERN_INVALID_ARGUMENT)
|
||||
}
|
||||
|
||||
// Read the old thread state
|
||||
var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee }
|
||||
|
||||
// 1. Decrement the stack pointer
|
||||
state.__rsp -= __uint64_t(MemoryLayout<Int>.size)
|
||||
|
||||
// 2. Save the old Instruction Pointer to the stack.
|
||||
if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) {
|
||||
pointer.pointee = state.__rip
|
||||
} else {
|
||||
return NSNumber(value: KERN_INVALID_ARGUMENT)
|
||||
}
|
||||
|
||||
// 3. Set the Instruction Pointer to the new function's address
|
||||
var f: @convention(c) () -> Void = raiseBadInstructionException
|
||||
withUnsafePointer(to: &f) {
|
||||
state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee }
|
||||
}
|
||||
|
||||
// Write the new thread state
|
||||
new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state }
|
||||
new_stateCnt.pointee = x86_THREAD_STATE64_COUNT
|
||||
|
||||
return NSNumber(value: KERN_SUCCESS)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,180 +18,192 @@
|
|||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#if (os(macOS) || os(iOS)) && arch(x86_64)
|
||||
|
||||
import Foundation
|
||||
import Swift
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
import CwlMachBadInstructionHandler
|
||||
#endif
|
||||
|
||||
#if arch(x86_64)
|
||||
|
||||
private enum PthreadError: Error { case code(Int32) }
|
||||
private enum MachExcServer: Error { case code(kern_return_t) }
|
||||
|
||||
/// A quick function for converting Mach error results into Swift errors
|
||||
private func kernCheck(_ f: () -> Int32) throws {
|
||||
let r = f()
|
||||
guard r == KERN_SUCCESS else {
|
||||
throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil)
|
||||
}
|
||||
private enum PthreadError: Error { case code(Int32) }
|
||||
private enum MachExcServer: Error { case code(kern_return_t) }
|
||||
|
||||
/// A quick function for converting Mach error results into Swift errors
|
||||
private func kernCheck(_ f: () -> Int32) throws {
|
||||
let r = f()
|
||||
guard r == KERN_SUCCESS else {
|
||||
throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil)
|
||||
}
|
||||
|
||||
extension request_mach_exception_raise_t {
|
||||
mutating func withMsgHeaderPointer<R>(in block: (UnsafeMutablePointer<mach_msg_header_t>) -> R) -> R {
|
||||
return withUnsafeMutablePointer(to: &self) { p -> R in
|
||||
return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
|
||||
return block(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
extension request_mach_exception_raise_t {
|
||||
mutating func withMsgHeaderPointer<R>(in block: (UnsafeMutablePointer<mach_msg_header_t>) -> R) -> R {
|
||||
return withUnsafeMutablePointer(to: &self) { p -> R in
|
||||
return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
|
||||
return block(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension reply_mach_exception_raise_state_t {
|
||||
mutating func withMsgHeaderPointer<R>(in block: (UnsafeMutablePointer<mach_msg_header_t>) -> R) -> R {
|
||||
return withUnsafeMutablePointer(to: &self) { p -> R in
|
||||
return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
|
||||
return block(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
extension reply_mach_exception_raise_state_t {
|
||||
mutating func withMsgHeaderPointer<R>(in block: (UnsafeMutablePointer<mach_msg_header_t>) -> R) -> R {
|
||||
return withUnsafeMutablePointer(to: &self) { p -> R in
|
||||
return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
|
||||
return block(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure used to store context associated with the Mach message port
|
||||
private struct MachContext {
|
||||
var masks = execTypesCountTuple<exception_mask_t>()
|
||||
var count: mach_msg_type_number_t = 0
|
||||
var ports = execTypesCountTuple<mach_port_t>()
|
||||
var behaviors = execTypesCountTuple<exception_behavior_t>()
|
||||
var flavors = execTypesCountTuple<thread_state_flavor_t>()
|
||||
var currentExceptionPort: mach_port_t = 0
|
||||
var handlerThread: pthread_t? = nil
|
||||
|
||||
/// A structure used to store context associated with the Mach message port
|
||||
private struct MachContext {
|
||||
var masks = execTypesCountTuple<exception_mask_t>()
|
||||
var count: mach_msg_type_number_t = 0
|
||||
var ports = execTypesCountTuple<mach_port_t>()
|
||||
var behaviors = execTypesCountTuple<exception_behavior_t>()
|
||||
var flavors = execTypesCountTuple<thread_state_flavor_t>()
|
||||
var currentExceptionPort: mach_port_t = 0
|
||||
var handlerThread: pthread_t? = nil
|
||||
|
||||
static func internalMutablePointers<R>(_ m: UnsafeMutablePointer<execTypesCountTuple<exception_mask_t>>, _ c: UnsafeMutablePointer<mach_msg_type_number_t>, _ p: UnsafeMutablePointer<execTypesCountTuple<mach_port_t>>, _ b: UnsafeMutablePointer<execTypesCountTuple<exception_behavior_t>>, _ f: UnsafeMutablePointer<execTypesCountTuple<thread_state_flavor_t>>, _ block: (UnsafeMutablePointer<exception_mask_t>, UnsafeMutablePointer<mach_msg_type_number_t>, UnsafeMutablePointer<mach_port_t>, UnsafeMutablePointer<exception_behavior_t>, UnsafeMutablePointer<thread_state_flavor_t>) -> R) -> R {
|
||||
return m.withMemoryRebound(to: exception_mask_t.self, capacity: 1) { masksPtr in
|
||||
return c.withMemoryRebound(to: mach_msg_type_number_t.self, capacity: 1) { countPtr in
|
||||
return p.withMemoryRebound(to: mach_port_t.self, capacity: 1) { portsPtr in
|
||||
return b.withMemoryRebound(to: exception_behavior_t.self, capacity: 1) { behaviorsPtr in
|
||||
return f.withMemoryRebound(to: thread_state_flavor_t.self, capacity: 1) { flavorsPtr in
|
||||
return block(masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
}
|
||||
static func internalMutablePointers<R>(_ m: UnsafeMutablePointer<execTypesCountTuple<exception_mask_t>>, _ c: UnsafeMutablePointer<mach_msg_type_number_t>, _ p: UnsafeMutablePointer<execTypesCountTuple<mach_port_t>>, _ b: UnsafeMutablePointer<execTypesCountTuple<exception_behavior_t>>, _ f: UnsafeMutablePointer<execTypesCountTuple<thread_state_flavor_t>>, _ block: (UnsafeMutablePointer<exception_mask_t>, UnsafeMutablePointer<mach_msg_type_number_t>, UnsafeMutablePointer<mach_port_t>, UnsafeMutablePointer<exception_behavior_t>, UnsafeMutablePointer<thread_state_flavor_t>) -> R) -> R {
|
||||
return m.withMemoryRebound(to: exception_mask_t.self, capacity: 1) { masksPtr in
|
||||
return c.withMemoryRebound(to: mach_msg_type_number_t.self, capacity: 1) { countPtr in
|
||||
return p.withMemoryRebound(to: mach_port_t.self, capacity: 1) { portsPtr in
|
||||
return b.withMemoryRebound(to: exception_behavior_t.self, capacity: 1) { behaviorsPtr in
|
||||
return f.withMemoryRebound(to: thread_state_flavor_t.self, capacity: 1) { flavorsPtr in
|
||||
return block(masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutating func withUnsafeMutablePointers<R>(in block: @escaping (UnsafeMutablePointer<exception_mask_t>, UnsafeMutablePointer<mach_msg_type_number_t>, UnsafeMutablePointer<mach_port_t>, UnsafeMutablePointer<exception_behavior_t>, UnsafeMutablePointer<thread_state_flavor_t>) -> R) -> R {
|
||||
return MachContext.internalMutablePointers(&masks, &count, &ports, &behaviors, &flavors, block)
|
||||
}
|
||||
}
|
||||
|
||||
/// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away).
|
||||
private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
|
||||
let context = arg.assumingMemoryBound(to: MachContext.self).pointee
|
||||
var request = request_mach_exception_raise_t()
|
||||
var reply = reply_mach_exception_raise_state_t()
|
||||
mutating func withUnsafeMutablePointers<R>(in block: @escaping (UnsafeMutablePointer<exception_mask_t>, UnsafeMutablePointer<mach_msg_type_number_t>, UnsafeMutablePointer<mach_port_t>, UnsafeMutablePointer<exception_behavior_t>, UnsafeMutablePointer<thread_state_flavor_t>) -> R) -> R {
|
||||
return MachContext.internalMutablePointers(&masks, &count, &ports, &behaviors, &flavors, block)
|
||||
}
|
||||
}
|
||||
|
||||
/// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away).
|
||||
private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
|
||||
let context = arg.assumingMemoryBound(to: MachContext.self).pointee
|
||||
var request = request_mach_exception_raise_t()
|
||||
var reply = reply_mach_exception_raise_state_t()
|
||||
|
||||
var handledfirstException = false
|
||||
repeat { do {
|
||||
// Request the next mach message from the port
|
||||
request.Head.msgh_local_port = context.currentExceptionPort
|
||||
request.Head.msgh_size = UInt32(MemoryLayout<request_mach_exception_raise_t>.size)
|
||||
let requestSize = request.Head.msgh_size
|
||||
try kernCheck { request.withMsgHeaderPointer { requestPtr in
|
||||
mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
|
||||
var handledfirstException = false
|
||||
repeat { do {
|
||||
// Request the next mach message from the port
|
||||
request.Head.msgh_local_port = context.currentExceptionPort
|
||||
request.Head.msgh_size = UInt32(MemoryLayout<request_mach_exception_raise_t>.size)
|
||||
let requestSize = request.Head.msgh_size
|
||||
try kernCheck { request.withMsgHeaderPointer { requestPtr in
|
||||
mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
// Prepare the reply structure
|
||||
reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0)
|
||||
reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL)
|
||||
reply.Head.msgh_remote_port = request.Head.msgh_remote_port
|
||||
reply.Head.msgh_size = UInt32(MemoryLayout<reply_mach_exception_raise_state_t>.size)
|
||||
reply.NDR = NDR_record
|
||||
|
||||
if !handledfirstException {
|
||||
// Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure
|
||||
guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in
|
||||
mach_exc_server(requestPtr, replyPtr)
|
||||
} }) != 0 else { throw MachExcServer.code(reply.RetCode) }
|
||||
|
||||
// Prepare the reply structure
|
||||
reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0)
|
||||
reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL)
|
||||
reply.Head.msgh_remote_port = request.Head.msgh_remote_port
|
||||
reply.Head.msgh_size = UInt32(MemoryLayout<reply_mach_exception_raise_state_t>.size)
|
||||
reply.NDR = NDR_record
|
||||
|
||||
if !handledfirstException {
|
||||
// Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure
|
||||
guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in
|
||||
mach_exc_server(requestPtr, replyPtr)
|
||||
} }) != 0 else { throw MachExcServer.code(reply.RetCode) }
|
||||
|
||||
handledfirstException = true
|
||||
} else {
|
||||
// If multiple fatal errors occur, don't handle subsquent errors (let the program crash)
|
||||
reply.RetCode = KERN_FAILURE
|
||||
}
|
||||
|
||||
// Send the reply
|
||||
let replySize = reply.Head.msgh_size
|
||||
try kernCheck { reply.withMsgHeaderPointer { replyPtr in
|
||||
mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
} catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) {
|
||||
// Port was already closed before we started or closed while we were listening.
|
||||
// This means the controlling thread shut down.
|
||||
return nil
|
||||
} catch {
|
||||
// Should never be reached but this is testing code, don't try to recover, just abort
|
||||
fatalError("Mach message error: \(error)")
|
||||
} } while true
|
||||
handledfirstException = true
|
||||
} else {
|
||||
// If multiple fatal errors occur, don't handle subsquent errors (let the program crash)
|
||||
reply.RetCode = KERN_FAILURE
|
||||
}
|
||||
|
||||
// Send the reply
|
||||
let replySize = reply.Head.msgh_size
|
||||
try kernCheck { reply.withMsgHeaderPointer { replyPtr in
|
||||
mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
} catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) {
|
||||
// Port was already closed before we started or closed while we were listening.
|
||||
// This means the controlling thread shut down.
|
||||
return nil
|
||||
} catch {
|
||||
// Should never be reached but this is testing code, don't try to recover, just abort
|
||||
fatalError("Mach message error: \(error)")
|
||||
} } while true
|
||||
}
|
||||
|
||||
/// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil.
|
||||
/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state.
|
||||
/// - parameter block: a function without parameters that will be run
|
||||
/// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`.
|
||||
public func catchBadInstruction(in block: @escaping () -> Void) -> BadInstructionException? {
|
||||
// Suppress Swift runtime's direct triggering of the debugger and exclusivity checking which crashes when we throw past it
|
||||
let previousExclusivity = _swift_disableExclusivityChecking
|
||||
let previousReporting = _swift_reportFatalErrorsToDebugger
|
||||
_swift_disableExclusivityChecking = true
|
||||
_swift_reportFatalErrorsToDebugger = false
|
||||
defer {
|
||||
_swift_reportFatalErrorsToDebugger = previousReporting
|
||||
_swift_disableExclusivityChecking = previousExclusivity
|
||||
}
|
||||
|
||||
/// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil.
|
||||
/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state.
|
||||
/// - parameter block: a function without parameters that will be run
|
||||
/// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`.
|
||||
public func catchBadInstruction(in block: () -> Void) -> BadInstructionException? {
|
||||
var context = MachContext()
|
||||
var result: BadInstructionException? = nil
|
||||
do {
|
||||
var handlerThread: pthread_t? = nil
|
||||
defer {
|
||||
// 8. Wait for the thread to terminate *if* we actually made it to the creation point
|
||||
// The mach port should be destroyed *before* calling pthread_join to avoid a deadlock.
|
||||
if handlerThread != nil {
|
||||
pthread_join(handlerThread!, nil)
|
||||
}
|
||||
var context = MachContext()
|
||||
var result: BadInstructionException? = nil
|
||||
do {
|
||||
var handlerThread: pthread_t? = nil
|
||||
defer {
|
||||
// 8. Wait for the thread to terminate *if* we actually made it to the creation point
|
||||
// The mach port should be destroyed *before* calling pthread_join to avoid a deadlock.
|
||||
if handlerThread != nil {
|
||||
pthread_join(handlerThread!, nil)
|
||||
}
|
||||
|
||||
try kernCheck {
|
||||
// 1. Create the mach port
|
||||
mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort)
|
||||
}
|
||||
defer {
|
||||
// 7. Cleanup the mach port
|
||||
mach_port_destroy(mach_task_self_, context.currentExceptionPort)
|
||||
}
|
||||
|
||||
try kernCheck {
|
||||
// 2. Configure the mach port
|
||||
mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND)
|
||||
}
|
||||
|
||||
let currentExceptionPtr = context.currentExceptionPort
|
||||
try kernCheck { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
|
||||
// 3. Apply the mach port as the handler for this thread
|
||||
thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, currentExceptionPtr, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
} }
|
||||
|
||||
defer { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
|
||||
// 6. Unapply the mach port
|
||||
_ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
} }
|
||||
|
||||
try withUnsafeMutablePointer(to: &context) { c throws in
|
||||
// 4. Create the thread
|
||||
let e = pthread_create(&handlerThread, nil, machMessageHandler, c)
|
||||
guard e == 0 else { throw PthreadError.code(e) }
|
||||
|
||||
// 5. Run the block
|
||||
result = BadInstructionException.catchException(in: block)
|
||||
}
|
||||
} catch {
|
||||
// Should never be reached but this is testing code, don't try to recover, just abort
|
||||
fatalError("Mach port error: \(error)")
|
||||
}
|
||||
return result
|
||||
|
||||
try kernCheck {
|
||||
// 1. Create the mach port
|
||||
mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort)
|
||||
}
|
||||
defer {
|
||||
// 7. Cleanup the mach port
|
||||
mach_port_destroy(mach_task_self_, context.currentExceptionPort)
|
||||
}
|
||||
|
||||
try kernCheck {
|
||||
// 2. Configure the mach port
|
||||
mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND)
|
||||
}
|
||||
|
||||
let currentExceptionPtr = context.currentExceptionPort
|
||||
try kernCheck { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
|
||||
// 3. Apply the mach port as the handler for this thread
|
||||
thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, currentExceptionPtr, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
} }
|
||||
|
||||
defer { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
|
||||
// 6. Unapply the mach port
|
||||
_ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
|
||||
} }
|
||||
|
||||
try withUnsafeMutablePointer(to: &context) { c throws in
|
||||
// 4. Create the thread
|
||||
let e = pthread_create(&handlerThread, nil, machMessageHandler, c)
|
||||
guard e == 0 else { throw PthreadError.code(e) }
|
||||
|
||||
// 5. Run the block
|
||||
result = BadInstructionException.catchException(in: block)
|
||||
}
|
||||
} catch {
|
||||
// Should never be reached but this is testing code, don't try to recover, just abort
|
||||
fatalError("Mach port error: \(error)")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
//
|
||||
// CwlCatchBadInstructionPosix.swift
|
||||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 8/02/2016.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if arch(x86_64)
|
||||
|
||||
// This file is an alternative implementation to CwlCatchBadInstruction.swift that uses a SIGILL signal action and setenv/longjmp instead of a Mach exception handler and Objective-C exception raising.
|
||||
//
|
||||
// WARNING:
|
||||
// This code is quick and dirty. It's a proof of concept for using a SIGILL handler and setjmp/longjmp where Mach exceptions and the Obj-C runtime aren't available. I ran the automated tests when I first wrote this code but I don't personally use it at all so by the time you're reading this comment, it probably broke and I didn't notice.
|
||||
// Obvious limitations:
|
||||
// * It doesn't work when debugging with lldb.
|
||||
// * It doesn't scope correctly to the thread (it's global)
|
||||
// * In violation of rules for signal handlers, it writes to the "red zone" on the stack
|
||||
// * It isn't re-entrant
|
||||
// * Plus all of the same caveats as the Mach exceptions version (doesn't play well with other handlers, probably leaks ARC memory, etc)
|
||||
// Treat it like a loaded shotgun. Don't point it at your face.
|
||||
|
||||
// This function is called from the signal handler to shut down the thread and return 1 (indicating a SIGILL was received).
|
||||
private func callThreadExit() {
|
||||
pthread_exit(UnsafeMutableRawPointer(bitPattern: 1))
|
||||
}
|
||||
|
||||
// When called, this signal handler simulates a function call to `callThreadExit`
|
||||
private func sigIllHandler(code: Int32, info: UnsafeMutablePointer<__siginfo>?, uap: UnsafeMutableRawPointer?) -> Void {
|
||||
guard let context = uap?.assumingMemoryBound(to: ucontext64_t.self) else { return }
|
||||
|
||||
// 1. Decrement the stack pointer
|
||||
context.pointee.uc_mcontext64.pointee.__ss.__rsp -= __uint64_t(MemoryLayout<Int>.size)
|
||||
|
||||
// 2. Save the old Instruction Pointer to the stack.
|
||||
let rsp = context.pointee.uc_mcontext64.pointee.__ss.__rsp
|
||||
if let ump = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(rsp)) {
|
||||
ump.pointee = rsp
|
||||
}
|
||||
|
||||
// 3. Set the Instruction Pointer to the new function's address
|
||||
var f: @convention(c) () -> Void = callThreadExit
|
||||
withUnsafePointer(to: &f) { $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { ptr in
|
||||
context.pointee.uc_mcontext64.pointee.__ss.__rip = ptr.pointee
|
||||
} }
|
||||
}
|
||||
|
||||
/// Without Mach exceptions or the Objective-C runtime, there's nothing to put in the exception object. It's really just a boolean – either a SIGILL was caught or not.
|
||||
public class BadInstructionException {
|
||||
}
|
||||
|
||||
/// Run the provided block. If a POSIX SIGILL is received, handle it and return a BadInstructionException (which is just an empty object in this POSIX signal version). Otherwise return nil.
|
||||
/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a SIGILL is received, the block will be interrupted using a C `longjmp`. The risks associated with abrupt jumps apply here: most Swift functions are *not* interrupt-safe. Memory may be leaked and the program will not necessarily be left in a safe state.
|
||||
/// - parameter block: a function without parameters that will be run
|
||||
/// - returns: if an SIGILL is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`.
|
||||
public func catchBadInstruction(block: @escaping () -> Void) -> BadInstructionException? {
|
||||
// Construct the signal action
|
||||
var sigActionPrev = sigaction()
|
||||
let action = __sigaction_u(__sa_sigaction: sigIllHandler)
|
||||
var sigActionNew = sigaction(__sigaction_u: action, sa_mask: sigset_t(), sa_flags: SA_SIGINFO)
|
||||
|
||||
// Install the signal action
|
||||
if sigaction(SIGILL, &sigActionNew, &sigActionPrev) != 0 {
|
||||
fatalError("Sigaction error: \(errno)")
|
||||
}
|
||||
|
||||
defer {
|
||||
// Restore the previous signal action
|
||||
if sigaction(SIGILL, &sigActionPrev, nil) != 0 {
|
||||
fatalError("Sigaction error: \(errno)")
|
||||
}
|
||||
}
|
||||
|
||||
var b = block
|
||||
let caught: Bool = withUnsafeMutablePointer(to: &b) { blockPtr in
|
||||
// Run the block on its own thread
|
||||
var handlerThread: pthread_t? = nil
|
||||
let e = pthread_create(&handlerThread, nil, { arg in
|
||||
(arg.assumingMemoryBound(to: (() -> Void).self).pointee)()
|
||||
return nil
|
||||
}, blockPtr)
|
||||
precondition(e == 0, "Unable to create thread")
|
||||
|
||||
// Wait for completion and get the result. It will be either `nil` or bitPattern 1
|
||||
var rawResult: UnsafeMutableRawPointer? = nil
|
||||
let e2 = pthread_join(handlerThread!, &rawResult)
|
||||
precondition(e2 == 0, "Thread join failed")
|
||||
return Int(bitPattern: rawResult) != 0
|
||||
}
|
||||
|
||||
return caught ? BadInstructionException() : nil
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,38 +18,38 @@
|
|||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#if (os(macOS) || os(iOS)) && arch(x86_64)
|
||||
|
||||
import Darwin
|
||||
|
||||
#if arch(x86_64)
|
||||
|
||||
// From /usr/include/mach/message.h
|
||||
// #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
|
||||
// #define MACH_MSGH_BITS_REMOTE(bits) \
|
||||
// ((bits) & MACH_MSGH_BITS_REMOTE_MASK)
|
||||
// #define MACH_MSGH_BITS(remote, local) /* legacy */ \
|
||||
// ((remote) | ((local) << 8))
|
||||
public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20
|
||||
public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) }
|
||||
public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) }
|
||||
|
||||
// From /usr/include/mach/exception_types.h
|
||||
// #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */
|
||||
// #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION)
|
||||
public let EXC_BAD_INSTRUCTION: UInt32 = 2
|
||||
public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION
|
||||
|
||||
// From /usr/include/mach/i386/thread_status.h
|
||||
// #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
|
||||
// ( sizeof (x86_thread_state64_t) / sizeof (int) ))
|
||||
public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout<x86_thread_state64_t>.size / MemoryLayout<Int32>.size)
|
||||
|
||||
public let EXC_TYPES_COUNT = 14
|
||||
public struct execTypesCountTuple<T: ExpressibleByIntegerLiteral> {
|
||||
// From /usr/include/mach/i386/exception.h
|
||||
// #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */
|
||||
public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
public init() {
|
||||
}
|
||||
// From /usr/include/mach/message.h
|
||||
// #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
|
||||
// #define MACH_MSGH_BITS_REMOTE(bits) \
|
||||
// ((bits) & MACH_MSGH_BITS_REMOTE_MASK)
|
||||
// #define MACH_MSGH_BITS(remote, local) /* legacy */ \
|
||||
// ((remote) | ((local) << 8))
|
||||
public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20
|
||||
public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) }
|
||||
public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) }
|
||||
|
||||
// From /usr/include/mach/exception_types.h
|
||||
// #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */
|
||||
// #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION)
|
||||
public let EXC_BAD_INSTRUCTION: UInt32 = 2
|
||||
public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION
|
||||
|
||||
// From /usr/include/mach/i386/thread_status.h
|
||||
// #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
|
||||
// ( sizeof (x86_thread_state64_t) / sizeof (int) ))
|
||||
public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout<x86_thread_state64_t>.size / MemoryLayout<Int32>.size)
|
||||
|
||||
public let EXC_TYPES_COUNT = 14
|
||||
public struct execTypesCountTuple<T: ExpressibleByIntegerLiteral> {
|
||||
// From /usr/include/mach/i386/exception.h
|
||||
// #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */
|
||||
public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
public init() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// CwlPreconditionTesting.h
|
||||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern bool _swift_reportFatalErrorsToDebugger;
|
||||
|
||||
//! Project version number for CwlUtils.
|
||||
FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber;
|
||||
|
||||
//! Project version string for CwlUtils.
|
||||
FOUNDATION_EXPORT const unsigned char CwlAssertingTestingVersionString[];
|
||||
|
||||
#include "CwlMachBadInstructionHandler.h"
|
||||
#include "CwlCatchException.h"
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// CwlPreconditionTesting.h
|
||||
// CwlPreconditionTesting
|
||||
//
|
||||
// Created by Matt Gallagher on 2016/01/10.
|
||||
// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern bool _swift_reportFatalErrorsToDebugger;
|
||||
|
||||
//! Project version number for CwlUtils.
|
||||
FOUNDATION_EXPORT double CwlPreconditionTesting_POSIXVersionNumber;
|
||||
|
||||
//! Project version string for CwlUtils.
|
||||
FOUNDATION_EXPORT const unsigned char CwlAssertingTesting_POSIXVersionString[];
|
|
@ -1,4 +1,4 @@
|
|||
# A sample Gemfile
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem 'cocoapods', '~> 1.6.0.rc.2'
|
||||
gem 'cocoapods', '~> 1.9'
|
||||
|
|
|
@ -1,76 +1,90 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.0)
|
||||
activesupport (4.2.11)
|
||||
CFPropertyList (3.0.2)
|
||||
activesupport (4.2.11.3)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
algoliasearch (1.27.3)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.0.2)
|
||||
cocoapods (1.6.0.rc.2)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.9.3)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.6.0.rc.2)
|
||||
cocoapods-deintegrate (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.9.3)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.2.2, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.3.1, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.2.0, < 3.0)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.6.6)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.3, >= 1.3.1)
|
||||
xcodeproj (>= 1.8.0, < 2.0)
|
||||
cocoapods-core (1.6.0.rc.2)
|
||||
ruby-macho (~> 1.4)
|
||||
xcodeproj (>= 1.14.0, < 2.0)
|
||||
cocoapods-core (1.9.3)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.2)
|
||||
cocoapods-downloader (1.2.2)
|
||||
netrc (~> 0.11)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.4)
|
||||
cocoapods-downloader (1.4.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.1.0)
|
||||
cocoapods-trunk (1.3.1)
|
||||
cocoapods-trunk (1.5.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.1.0)
|
||||
cocoapods-try (1.2.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.4)
|
||||
concurrent-ruby (1.1.6)
|
||||
escape (0.0.4)
|
||||
fourflusher (2.2.0)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
ffi (1.13.1)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
httpclient (2.8.3)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
minitest (5.11.3)
|
||||
json (2.3.1)
|
||||
minitest (5.14.1)
|
||||
molinillo (0.6.6)
|
||||
nanaimo (0.2.6)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
ruby-macho (1.3.1)
|
||||
ruby-macho (1.4.0)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.5)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
xcodeproj (1.8.0)
|
||||
xcodeproj (1.17.1)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.6)
|
||||
nanaimo (~> 0.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (~> 1.6.0.rc.2)
|
||||
cocoapods (~> 1.9)
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.2
|
||||
2.1.4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "Nimble"
|
||||
s.version = "8.0.0"
|
||||
s.version = "9.0.0"
|
||||
s.summary = "A Matcher Framework for Swift and Objective-C"
|
||||
s.description = <<-DESC
|
||||
Use Nimble to express the expected outcomes of Swift or Objective-C expressions. Inspired by Cedar.
|
||||
|
@ -8,7 +8,7 @@ Pod::Spec.new do |s|
|
|||
s.homepage = "https://github.com/Quick/Nimble"
|
||||
s.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
s.author = "Quick Contributors"
|
||||
s.ios.deployment_target = "8.0"
|
||||
s.ios.deployment_target = "9.0"
|
||||
s.osx.deployment_target = "10.10"
|
||||
s.tvos.deployment_target = "9.0"
|
||||
s.source = { :git => "https://github.com/Quick/Nimble.git",
|
||||
|
@ -21,15 +21,13 @@ Pod::Spec.new do |s|
|
|||
]
|
||||
|
||||
s.osx.exclude_files = [
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPosixPreconditionTesting/CwlCatchBadInstructionPosix.swift",
|
||||
]
|
||||
s.ios.exclude_files = [
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPosixPreconditionTesting/CwlCatchBadInstructionPosix.swift",
|
||||
]
|
||||
s.tvos.exclude_files = [
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift",
|
||||
"Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift",
|
||||
|
@ -44,12 +42,17 @@ Pod::Spec.new do |s|
|
|||
s.compiler_flags = '-DPRODUCT_NAME=Nimble/Nimble'
|
||||
s.pod_target_xcconfig = {
|
||||
'APPLICATION_EXTENSION_API_ONLY' => 'YES',
|
||||
'DEFINES_MODULE' => 'YES',
|
||||
'ENABLE_BITCODE' => 'NO',
|
||||
'ENABLE_TESTING_SEARCH_PATHS' => 'YES',
|
||||
'OTHER_LDFLAGS' => '$(inherited) -weak-lswiftXCTest -Xlinker -no_application_extension',
|
||||
'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings',
|
||||
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"',
|
||||
}
|
||||
|
||||
s.cocoapods_version = '>= 1.4.0'
|
||||
s.swift_version = '4.2'
|
||||
if s.respond_to?(:swift_versions) then
|
||||
s.swift_versions = ['5.0']
|
||||
else
|
||||
s.swift_version = '5.0'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 53;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
|
@ -21,6 +21,9 @@
|
|||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0477153523B740AD00402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
|
||||
0477153623B740B700402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
|
||||
0477153723B740B800402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; };
|
||||
1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
|
||||
1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
|
||||
1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; };
|
||||
|
@ -62,8 +65,6 @@
|
|||
1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; };
|
||||
1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; };
|
||||
1F299EAC19627B2D002641AF /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; };
|
||||
1F43728A1A1B343800EB80F8 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD251968AB07008ED995 /* Functional.swift */; };
|
||||
1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD251968AB07008ED995 /* Functional.swift */; };
|
||||
1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; };
|
||||
1F43728D1A1B343D00EB80F8 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; };
|
||||
1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; };
|
||||
|
@ -142,7 +143,6 @@
|
|||
1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; };
|
||||
1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; };
|
||||
1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59651B551EE6002D767E /* ThrowError.swift */; };
|
||||
1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD251968AB07008ED995 /* Functional.swift */; };
|
||||
1F5DF18C1BDCA0F500C3A531 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; };
|
||||
1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; };
|
||||
1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; };
|
||||
|
@ -284,15 +284,18 @@
|
|||
29EA59641B551ED2002D767E /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; };
|
||||
29EA59661B551EE6002D767E /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59651B551EE6002D767E /* ThrowError.swift */; };
|
||||
29EA59671B551EE6002D767E /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59651B551EE6002D767E /* ThrowError.swift */; };
|
||||
347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */; };
|
||||
347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */; };
|
||||
347155CC1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */; };
|
||||
472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; };
|
||||
472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; };
|
||||
472FD13A1B9E0A9F00C7B8DA /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; };
|
||||
472FD13B1B9E0CFE00C7B8DA /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; };
|
||||
4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; };
|
||||
4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; };
|
||||
62FB326223B78BF90047BED9 /* BeginWithPrefix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326123B78BF90047BED9 /* BeginWithPrefix.swift */; };
|
||||
62FB326323B78BF90047BED9 /* BeginWithPrefix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326123B78BF90047BED9 /* BeginWithPrefix.swift */; };
|
||||
62FB326423B78BF90047BED9 /* BeginWithPrefix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326123B78BF90047BED9 /* BeginWithPrefix.swift */; };
|
||||
62FB326923B78D4F0047BED9 /* BeginWithPrefixTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326523B78D4A0047BED9 /* BeginWithPrefixTest.swift */; };
|
||||
62FB326A23B78D500047BED9 /* BeginWithPrefixTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326523B78D4A0047BED9 /* BeginWithPrefixTest.swift */; };
|
||||
62FB326B23B78D510047BED9 /* BeginWithPrefixTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FB326523B78D4A0047BED9 /* BeginWithPrefixTest.swift */; };
|
||||
6CAEDD0A1CAEA86F003F1584 /* LinuxSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */; };
|
||||
6CAEDD0B1CAEA86F003F1584 /* LinuxSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */; };
|
||||
6CAEDD0C1CAEA86F003F1584 /* LinuxSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */; };
|
||||
|
@ -353,7 +356,10 @@
|
|||
B20058C520E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
|
||||
B20058C620E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
|
||||
B20058C720E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
|
||||
CD037213207DCC580047AF28 /* XCTestManifests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD037212207DCC580047AF28 /* XCTestManifests.swift */; };
|
||||
CD3D9A79232647BC00802581 /* CwlCatchBadInstructionPosix.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3D9A78232647BC00802581 /* CwlCatchBadInstructionPosix.swift */; };
|
||||
CD4C8F092464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */; };
|
||||
CD4C8F0A2464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */; };
|
||||
CD4C8F0B2464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */; };
|
||||
CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; };
|
||||
CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; };
|
||||
CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; };
|
||||
|
@ -380,6 +386,12 @@
|
|||
CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; };
|
||||
CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; };
|
||||
CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; };
|
||||
CDBC39B92462EA7D00069677 /* PredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBC39B82462EA7D00069677 /* PredicateTest.swift */; };
|
||||
CDBC39BA2462EA7D00069677 /* PredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBC39B82462EA7D00069677 /* PredicateTest.swift */; };
|
||||
CDBC39BB2462EA7D00069677 /* PredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBC39B82462EA7D00069677 /* PredicateTest.swift */; };
|
||||
CDC157912511957100EAA480 /* DSLTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC157902511957100EAA480 /* DSLTest.swift */; };
|
||||
CDC157922511957100EAA480 /* DSLTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC157902511957100EAA480 /* DSLTest.swift */; };
|
||||
CDC157932511957100EAA480 /* DSLTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC157902511957100EAA480 /* DSLTest.swift */; };
|
||||
CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
|
||||
CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
|
||||
CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; };
|
||||
|
@ -395,8 +407,6 @@
|
|||
CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; };
|
||||
CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */; };
|
||||
CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */; };
|
||||
CDFB6A431F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CDFB6A441F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; };
|
||||
CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; };
|
||||
CDFB6A491F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -404,9 +414,6 @@
|
|||
CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */; };
|
||||
CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */; };
|
||||
CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; };
|
||||
CDFB6A501F7E085600AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; };
|
||||
CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */; };
|
||||
CDFB6A521F7E089F00AD8CC7 /* CwlPreconditionTesting_POSIX.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
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 */; };
|
||||
|
@ -493,6 +500,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0477153423B740AD00402D4E /* DispatchTimeInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchTimeInterval.swift; sourceTree = "<group>"; };
|
||||
1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = "<group>"; };
|
||||
1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTest.swift; sourceTree = "<group>"; };
|
||||
1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = "<group>"; };
|
||||
|
@ -588,7 +596,6 @@
|
|||
1FD8CD1C1968AB07008ED995 /* Equal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Equal.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = "<group>"; };
|
||||
1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = "<group>"; };
|
||||
1FD8CD261968AB07008ED995 /* Await.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Await.swift; sourceTree = "<group>"; };
|
||||
1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = "<group>"; };
|
||||
1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = "<group>"; };
|
||||
|
@ -596,10 +603,11 @@
|
|||
1FE661561E6574E20035F243 /* ExpectationMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpectationMessage.swift; sourceTree = "<group>"; };
|
||||
29EA59621B551ED2002D767E /* ThrowErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowErrorTest.swift; sourceTree = "<group>"; };
|
||||
29EA59651B551EE6002D767E /* ThrowError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowError.swift; sourceTree = "<group>"; };
|
||||
347155C91C337C8900549F03 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseProvider.swift; sourceTree = "<group>"; };
|
||||
472FD1341B9E085700C7B8DA /* HaveCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCount.swift; sourceTree = "<group>"; };
|
||||
472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCountTest.swift; sourceTree = "<group>"; };
|
||||
4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCountTest.m; sourceTree = "<group>"; };
|
||||
62FB326123B78BF90047BED9 /* BeginWithPrefix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeginWithPrefix.swift; sourceTree = "<group>"; };
|
||||
62FB326523B78D4A0047BED9 /* BeginWithPrefixTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeginWithPrefixTest.swift; sourceTree = "<group>"; };
|
||||
6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = "<group>"; };
|
||||
7A0A26221E7F52360092A34E /* ToSucceed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceed.swift; sourceTree = "<group>"; };
|
||||
7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceedTest.swift; sourceTree = "<group>"; };
|
||||
|
@ -621,16 +629,16 @@
|
|||
AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = "<group>"; };
|
||||
B20058C020E92C7500C1264D /* ElementsEqual.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqual.swift; sourceTree = "<group>"; };
|
||||
B20058C420E92CE400C1264D /* ElementsEqualTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqualTest.swift; sourceTree = "<group>"; };
|
||||
CD037212207DCC580047AF28 /* XCTestManifests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = "<group>"; };
|
||||
CD3D9A78232647BC00802581 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = "<group>"; };
|
||||
CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousDeprecatedTest.swift; sourceTree = "<group>"; };
|
||||
CDBC39B82462EA7D00069677 /* PredicateTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredicateTest.swift; sourceTree = "<group>"; };
|
||||
CDC157902511957100EAA480 /* DSLTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSLTest.swift; sourceTree = "<group>"; };
|
||||
CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = "<group>"; };
|
||||
CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = "<group>"; };
|
||||
CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = "<group>"; };
|
||||
CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = "<group>"; };
|
||||
CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = "<group>"; };
|
||||
CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = "<group>"; };
|
||||
CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = "<group>"; };
|
||||
CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = "<group>"; };
|
||||
CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = "<group>"; };
|
||||
CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = "<group>"; };
|
||||
CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = "<group>"; };
|
||||
CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = "<group>"; };
|
||||
|
@ -699,7 +707,6 @@
|
|||
children = (
|
||||
1F14FB63194180C5009F2A08 /* utils.swift */,
|
||||
1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */,
|
||||
347155C91C337C8900549F03 /* XCTestCaseProvider.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -777,11 +784,13 @@
|
|||
1F1A74381940169200FFFC47 /* NimbleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1F925EE5195C121200ED456B /* AsynchronousTest.swift */,
|
||||
CDC157902511957100EAA480 /* DSLTest.swift */,
|
||||
CDBC39B82462EA7D00069677 /* PredicateTest.swift */,
|
||||
1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */,
|
||||
CD4C8F082464365300A7BDE0 /* SynchronousDeprecatedTest.swift */,
|
||||
1F925EE5195C121200ED456B /* AsynchronousTest.swift */,
|
||||
965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */,
|
||||
6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */,
|
||||
CD037212207DCC580047AF28 /* XCTestManifests.swift */,
|
||||
1FFD729A1963FC8200CD29A2 /* objc */,
|
||||
1F14FB61194180A7009F2A08 /* Helpers */,
|
||||
1F925EE3195C11B000ED456B /* Matchers */,
|
||||
|
@ -807,6 +816,7 @@
|
|||
1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */,
|
||||
1F925EF5195C147800ED456B /* BeCloseToTest.swift */,
|
||||
1F299EAA19627B2D002641AF /* BeEmptyTest.swift */,
|
||||
62FB326523B78D4A0047BED9 /* BeginWithPrefixTest.swift */,
|
||||
1F925EFB195C186800ED456B /* BeginWithTest.swift */,
|
||||
1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */,
|
||||
1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */,
|
||||
|
@ -819,18 +829,18 @@
|
|||
1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */,
|
||||
7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */,
|
||||
1F925F01195C189500ED456B /* ContainTest.swift */,
|
||||
B20058C420E92CE400C1264D /* ElementsEqualTest.swift */,
|
||||
1F925EFE195C187600ED456B /* EndWithTest.swift */,
|
||||
1F925F04195C18B700ED456B /* EqualTest.swift */,
|
||||
B20058C420E92CE400C1264D /* ElementsEqualTest.swift */,
|
||||
472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */,
|
||||
DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */,
|
||||
1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */,
|
||||
29EA59621B551ED2002D767E /* ThrowErrorTest.swift */,
|
||||
7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */,
|
||||
A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */,
|
||||
1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */,
|
||||
AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */,
|
||||
DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */,
|
||||
1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */,
|
||||
1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */,
|
||||
A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */,
|
||||
7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */,
|
||||
1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */,
|
||||
29EA59621B551ED2002D767E /* ThrowErrorTest.swift */,
|
||||
7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */,
|
||||
);
|
||||
path = Matchers;
|
||||
|
@ -861,6 +871,7 @@
|
|||
1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */,
|
||||
1FD8CD101968AB07008ED995 /* BeEmpty.swift */,
|
||||
1FD8CD111968AB07008ED995 /* BeginWith.swift */,
|
||||
62FB326123B78BF90047BED9 /* BeginWithPrefix.swift */,
|
||||
1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */,
|
||||
1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */,
|
||||
1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */,
|
||||
|
@ -871,9 +882,9 @@
|
|||
1F91DD301C74BF61002C309F /* BeVoid.swift */,
|
||||
1FD8CD1A1968AB07008ED995 /* Contain.swift */,
|
||||
7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */,
|
||||
B20058C020E92C7500C1264D /* ElementsEqual.swift */,
|
||||
1FD8CD1B1968AB07008ED995 /* EndWith.swift */,
|
||||
1FD8CD1C1968AB07008ED995 /* Equal.swift */,
|
||||
B20058C020E92C7500C1264D /* ElementsEqual.swift */,
|
||||
472FD1341B9E085700C7B8DA /* HaveCount.swift */,
|
||||
DDB4D5EC19FE43C200E9D9FE /* Match.swift */,
|
||||
1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */,
|
||||
|
@ -882,8 +893,8 @@
|
|||
1FCF91521C61C8A400B15DCB /* PostNotification.swift */,
|
||||
1FA0C3FE1E30B14500623165 /* Predicate.swift */,
|
||||
1FD8CD1E1968AB07008ED995 /* RaisesException.swift */,
|
||||
7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */,
|
||||
A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */,
|
||||
7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */,
|
||||
964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */,
|
||||
29EA59651B551EE6002D767E /* ThrowError.swift */,
|
||||
7A0A26221E7F52360092A34E /* ToSucceed.swift */,
|
||||
|
@ -894,11 +905,11 @@
|
|||
1FD8CD241968AB07008ED995 /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1FD8CD251968AB07008ED995 /* Functional.swift */,
|
||||
1FD8CD261968AB07008ED995 /* Await.swift */,
|
||||
1FD8CD271968AB07008ED995 /* SourceLocation.swift */,
|
||||
1FD8CD281968AB07008ED995 /* Stringers.swift */,
|
||||
AE4BA9AC1C88DDB500B73906 /* Errors.swift */,
|
||||
0477153423B740AD00402D4E /* DispatchTimeInterval.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
@ -940,6 +951,14 @@
|
|||
path = objc;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CD3D9A77232647BC00802581 /* CwlPosixPreconditionTesting */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD3D9A78232647BC00802581 /* CwlCatchBadInstructionPosix.swift */,
|
||||
);
|
||||
path = CwlPosixPreconditionTesting;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -965,6 +984,7 @@
|
|||
children = (
|
||||
CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */,
|
||||
CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */,
|
||||
CD3D9A77232647BC00802581 /* CwlPosixPreconditionTesting */,
|
||||
);
|
||||
name = CwlPreconditionTesting;
|
||||
path = CwlPreconditionTesting/Sources;
|
||||
|
@ -1000,30 +1020,11 @@
|
|||
children = (
|
||||
CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */,
|
||||
CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */,
|
||||
CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */,
|
||||
CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */,
|
||||
CDFB6A2F1F7E082400AD8CC7 /* Mach */,
|
||||
CDFB6A311F7E082400AD8CC7 /* Posix */,
|
||||
);
|
||||
path = CwlPreconditionTesting;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDFB6A2F1F7E082400AD8CC7 /* Mach */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */,
|
||||
);
|
||||
path = Mach;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDFB6A311F7E082400AD8CC7 /* Posix */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */,
|
||||
);
|
||||
path = Posix;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1052,7 +1053,6 @@
|
|||
files = (
|
||||
CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */,
|
||||
CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */,
|
||||
CDFB6A441F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */,
|
||||
1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */,
|
||||
1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */,
|
||||
1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */,
|
||||
|
@ -1064,11 +1064,9 @@
|
|||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CDFB6A521F7E089F00AD8CC7 /* CwlPreconditionTesting_POSIX.h in Headers */,
|
||||
1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */,
|
||||
1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */,
|
||||
1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */,
|
||||
CDFB6A501F7E085600AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */,
|
||||
1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -1080,7 +1078,6 @@
|
|||
CDFB6A491F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */,
|
||||
CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */,
|
||||
1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */,
|
||||
CDFB6A431F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */,
|
||||
1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */,
|
||||
1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */,
|
||||
1F925EC7195C0DD100ED456B /* Nimble.h in Headers */,
|
||||
|
@ -1211,7 +1208,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = "Jeff Hui";
|
||||
TargetAttributes = {
|
||||
1F1A74281940169200FFFC47 = {
|
||||
|
@ -1247,11 +1244,12 @@
|
|||
};
|
||||
};
|
||||
buildConfigurationList = 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
compatibilityVersion = "Xcode 11.4";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 1F1A741F1940169200FFFC47;
|
||||
productRefGroup = 1F1A742A1940169200FFFC47 /* Products */;
|
||||
|
@ -1344,9 +1342,9 @@
|
|||
1F43728D1A1B343D00EB80F8 /* SourceLocation.swift in Sources */,
|
||||
1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */,
|
||||
1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */,
|
||||
1F43728A1A1B343800EB80F8 /* Functional.swift in Sources */,
|
||||
AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */,
|
||||
1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */,
|
||||
0477153623B740B700402D4E /* DispatchTimeInterval.swift in Sources */,
|
||||
7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */,
|
||||
1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */,
|
||||
1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */,
|
||||
|
@ -1360,6 +1358,7 @@
|
|||
1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */,
|
||||
1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */,
|
||||
29EA59661B551EE6002D767E /* ThrowError.swift in Sources */,
|
||||
62FB326323B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
|
||||
1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */,
|
||||
1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */,
|
||||
1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */,
|
||||
|
@ -1406,9 +1405,11 @@
|
|||
files = (
|
||||
1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */,
|
||||
1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */,
|
||||
62FB326A23B78D500047BED9 /* BeginWithPrefixTest.swift in Sources */,
|
||||
1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */,
|
||||
1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */,
|
||||
1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */,
|
||||
CDBC39BA2462EA7D00069677 /* PredicateTest.swift in Sources */,
|
||||
1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */,
|
||||
1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */,
|
||||
1F14FB64194180C5009F2A08 /* utils.swift in Sources */,
|
||||
|
@ -1430,7 +1431,9 @@
|
|||
1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */,
|
||||
1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */,
|
||||
1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */,
|
||||
CDC157922511957100EAA480 /* DSLTest.swift in Sources */,
|
||||
7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */,
|
||||
CD4C8F0A2464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */,
|
||||
A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */,
|
||||
1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */,
|
||||
1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */,
|
||||
|
@ -1457,7 +1460,6 @@
|
|||
DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */,
|
||||
1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */,
|
||||
1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */,
|
||||
347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */,
|
||||
4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */,
|
||||
1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */,
|
||||
7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */,
|
||||
|
@ -1482,8 +1484,10 @@
|
|||
1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */,
|
||||
1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */,
|
||||
7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */,
|
||||
62FB326423B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
|
||||
1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */,
|
||||
A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */,
|
||||
CD3D9A79232647BC00802581 /* CwlCatchBadInstructionPosix.swift in Sources */,
|
||||
1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */,
|
||||
1F1871E81CA8A18400A34BF2 /* Async.swift in Sources */,
|
||||
1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */,
|
||||
|
@ -1518,7 +1522,6 @@
|
|||
1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */,
|
||||
1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */,
|
||||
1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */,
|
||||
CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */,
|
||||
1F5DF18C1BDCA0F500C3A531 /* Await.swift in Sources */,
|
||||
1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */,
|
||||
1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */,
|
||||
|
@ -1531,8 +1534,8 @@
|
|||
CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */,
|
||||
1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */,
|
||||
7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */,
|
||||
0477153723B740B800402D4E /* DispatchTimeInterval.swift in Sources */,
|
||||
7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */,
|
||||
1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */,
|
||||
1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -1543,9 +1546,11 @@
|
|||
files = (
|
||||
CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */,
|
||||
CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */,
|
||||
62FB326923B78D4F0047BED9 /* BeginWithPrefixTest.swift in Sources */,
|
||||
1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */,
|
||||
1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */,
|
||||
CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */,
|
||||
CDBC39BB2462EA7D00069677 /* PredicateTest.swift in Sources */,
|
||||
CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */,
|
||||
CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */,
|
||||
1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */,
|
||||
|
@ -1567,7 +1572,9 @@
|
|||
CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */,
|
||||
CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */,
|
||||
1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */,
|
||||
CDC157932511957100EAA480 /* DSLTest.swift in Sources */,
|
||||
1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */,
|
||||
CD4C8F0B2464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */,
|
||||
A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */,
|
||||
1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */,
|
||||
1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */,
|
||||
|
@ -1591,7 +1598,6 @@
|
|||
7A6AB2C41E7F547E00A2F694 /* ToSucceedTest.swift in Sources */,
|
||||
CD79C9A71D2CC848004B6F9A /* ObjCBeGreaterThanTest.m in Sources */,
|
||||
CD79C9A51D2CC848004B6F9A /* ObjCBeginWithTest.m in Sources */,
|
||||
347155CC1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */,
|
||||
1F5DF1AA1BDCA10200C3A531 /* RaisesExceptionTest.swift in Sources */,
|
||||
1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */,
|
||||
CD79C9AF1D2CC848004B6F9A /* ObjCContainTest.m in Sources */,
|
||||
|
@ -1624,8 +1630,8 @@
|
|||
1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */,
|
||||
1F1871E71CA8A18400A34BF2 /* Async.swift in Sources */,
|
||||
1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */,
|
||||
1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */,
|
||||
AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */,
|
||||
0477153523B740AD00402D4E /* DispatchTimeInterval.swift in Sources */,
|
||||
1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */,
|
||||
1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */,
|
||||
1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */,
|
||||
|
@ -1639,6 +1645,7 @@
|
|||
1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */,
|
||||
DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */,
|
||||
29EA59671B551EE6002D767E /* ThrowError.swift in Sources */,
|
||||
62FB326223B78BF90047BED9 /* BeginWithPrefix.swift in Sources */,
|
||||
1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */,
|
||||
1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */,
|
||||
1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */,
|
||||
|
@ -1685,16 +1692,17 @@
|
|||
files = (
|
||||
1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */,
|
||||
1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */,
|
||||
62FB326B23B78D510047BED9 /* BeginWithPrefixTest.swift in Sources */,
|
||||
1F925F00195C187600ED456B /* EndWithTest.swift in Sources */,
|
||||
1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */,
|
||||
1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */,
|
||||
CDBC39B92462EA7D00069677 /* PredicateTest.swift in Sources */,
|
||||
1F4A56671A3B305F009E1637 /* ObjCAsyncTest.m in Sources */,
|
||||
1F925EFD195C186800ED456B /* BeginWithTest.swift in Sources */,
|
||||
1F925EE2195C0DFD00ED456B /* utils.swift in Sources */,
|
||||
DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */,
|
||||
1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */,
|
||||
1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */,
|
||||
CD037213207DCC580047AF28 /* XCTestManifests.swift in Sources */,
|
||||
7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */,
|
||||
1F925F03195C189500ED456B /* ContainTest.swift in Sources */,
|
||||
A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */,
|
||||
|
@ -1710,7 +1718,9 @@
|
|||
1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */,
|
||||
1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */,
|
||||
1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */,
|
||||
CDC157912511957100EAA480 /* DSLTest.swift in Sources */,
|
||||
1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */,
|
||||
CD4C8F092464365300A7BDE0 /* SynchronousDeprecatedTest.swift in Sources */,
|
||||
7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */,
|
||||
A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */,
|
||||
1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */,
|
||||
|
@ -1737,7 +1747,6 @@
|
|||
DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */,
|
||||
1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */,
|
||||
1F0648D51963AAB2001F9C46 /* SynchronousTest.swift in Sources */,
|
||||
347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */,
|
||||
4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */,
|
||||
1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */,
|
||||
7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */,
|
||||
|
@ -1809,6 +1818,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
@ -1839,6 +1849,7 @@
|
|||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_TESTING_SEARCH_PATHS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
|
@ -1855,16 +1866,18 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
SWIFT_VERSION = 4.2;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -1875,6 +1888,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
@ -1905,6 +1919,7 @@
|
|||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTING_SEARCH_PATHS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
@ -1914,15 +1929,19 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -suppress-warnings";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
|
||||
SWIFT_VERSION = 4.2;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
|
@ -1932,16 +1951,13 @@
|
|||
1F1A74401940169200FFFC47 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)",
|
||||
|
@ -1950,37 +1966,38 @@
|
|||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1F1A74411940169200FFFC47 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)",
|
||||
"$(inherited)",
|
||||
|
@ -1988,20 +2005,26 @@
|
|||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -2009,20 +2032,22 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
METAL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_CODE_SIGN_FLAGS = "--verbose";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -2031,33 +2056,33 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
METAL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CODE_SIGN_FLAGS = "--verbose";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1F5DF1661BDCA0CE00C3A531 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
|
@ -2066,15 +2091,17 @@
|
|||
);
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
|
@ -2082,12 +2109,14 @@
|
|||
SDKROOT = appletvos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1F5DF1671BDCA0CE00C3A531 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
|
@ -2095,10 +2124,6 @@
|
|||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)",
|
||||
|
@ -2106,23 +2131,27 @@
|
|||
);
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = appletvos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -2130,19 +2159,20 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_CODE_SIGN_FLAGS = "--verbose";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
SDKROOT = appletvos;
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -2151,35 +2181,34 @@
|
|||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CODE_SIGN_FLAGS = "--verbose";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
SDKROOT = appletvos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = 3;
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1F925EC1195C0D6300ED456B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
|
@ -2189,38 +2218,37 @@
|
|||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
VALID_ARCHS = x86_64;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1F925EC2195C0D6300ED456B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)",
|
||||
|
@ -2229,23 +2257,26 @@
|
|||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
INFOPLIST_FILE = Sources/Nimble/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-weak_framework",
|
||||
XCTest,
|
||||
"-weak-lswiftXCTest",
|
||||
"-Xlinker",
|
||||
"-no_application_extension",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_MODULE_NAME = Nimble;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALID_ARCHS = x86_64;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -2254,16 +2285,17 @@
|
|||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
|
@ -2278,17 +2310,19 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/NimbleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
METAL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = NimbleTests;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -29,7 +29,8 @@
|
|||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1F1A74331940169200FFFC47"
|
||||
|
@ -39,8 +40,6 @@
|
|||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -62,8 +61,6 @@
|
|||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -29,7 +29,8 @@
|
|||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1F925EB6195C0D6300ED456B"
|
||||
|
@ -39,8 +40,6 @@
|
|||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -62,8 +61,6 @@
|
|||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -27,18 +27,6 @@
|
|||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1F5DF15D1BDCA0CE00C3A531"
|
||||
BuildableName = "NimbleTests.xctest"
|
||||
BlueprintName = "Nimble-tvOSTests"
|
||||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
@ -48,8 +36,19 @@
|
|||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1F5DF15D1BDCA0CE00C3A531"
|
||||
BuildableName = "NimbleTests.xctest"
|
||||
BlueprintName = "Nimble-tvOSTests"
|
||||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -70,8 +69,6 @@
|
|||
ReferencedContainer = "container:Nimble.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
25
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package.resolved
vendored
Normal file
25
Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package.resolved
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "CwlCatchException",
|
||||
"repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "f809deb30dc5c9d9b78c872e553261a61177721a",
|
||||
"version": "2.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "CwlPreconditionTesting",
|
||||
"repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "02b7a39a99c4da27abe03cab2053a9034379639f",
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
|
@ -1,15 +1,30 @@
|
|||
// swift-tools-version:4.2
|
||||
// swift-tools-version:5.2
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Nimble",
|
||||
platforms: [
|
||||
.macOS(.v10_10), .iOS(.v9), .tvOS(.v9)
|
||||
],
|
||||
products: [
|
||||
.library(name: "Nimble", targets: ["Nimble"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", .upToNextMajor(from: "2.0.0")),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "Nimble",
|
||||
dependencies: []
|
||||
dependencies: {
|
||||
#if os(macOS)
|
||||
return [
|
||||
"CwlPreconditionTesting",
|
||||
.product(name: "CwlPosixPreconditionTesting", package: "CwlPreconditionTesting")
|
||||
]
|
||||
#else
|
||||
return []
|
||||
#endif
|
||||
}()
|
||||
),
|
||||
.testTarget(
|
||||
name: "NimbleTests",
|
||||
|
@ -17,5 +32,5 @@ let package = Package(
|
|||
exclude: ["objc"]
|
||||
),
|
||||
],
|
||||
swiftLanguageVersions: [.v4_2]
|
||||
swiftLanguageVersions: [.v5]
|
||||
)
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
[![Build Status](https://travis-ci.org/Quick/Nimble.svg?branch=master)](https://travis-ci.org/Quick/Nimble)
|
||||
[![CocoaPods](https://img.shields.io/cocoapods/v/Nimble.svg)](https://cocoapods.org/pods/Nimble)
|
||||
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
|
||||
[![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio)
|
||||
[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble)
|
||||
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
|
||||
|
||||
Use Nimble to express the expected outcomes of Swift
|
||||
or Objective-C expressions. Inspired by
|
||||
|
@ -70,6 +70,7 @@ expect(ocean.isClean).toEventually(beTruthy())
|
|||
- [Installing Nimble](#installing-nimble)
|
||||
- [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule)
|
||||
- [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods)
|
||||
- [Installing Nimble via Accio](#installing-nimble-via-accio)
|
||||
- [Using Nimble without XCTest](#using-nimble-without-xctest)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
@ -344,10 +345,10 @@ cases, use the `timeout` parameter:
|
|||
// Swift
|
||||
|
||||
// Waits three seconds for ocean to contain "starfish":
|
||||
expect(ocean).toEventually(contain("starfish"), timeout: 3)
|
||||
expect(ocean).toEventually(contain("starfish"), timeout: .seconds(3))
|
||||
|
||||
// Evaluate someValue every 0.2 seconds repeatedly until it equals 100, or fails if it timeouts after 5.5 seconds.
|
||||
expect(someValue).toEventually(equal(100), timeout: 5.5, pollInterval: 0.2)
|
||||
expect(someValue).toEventually(equal(100), timeout: .milliseconds(5500), pollInterval: .milliseconds(200))
|
||||
```
|
||||
|
||||
```objc
|
||||
|
@ -386,7 +387,7 @@ waitUntil(^(void (^done)(void)){
|
|||
```swift
|
||||
// Swift
|
||||
|
||||
waitUntil(timeout: 10) { done in
|
||||
waitUntil(timeout: .seconds(10)) { done in
|
||||
ocean.goFish { success in
|
||||
expect(success).to(beTrue())
|
||||
done()
|
||||
|
@ -418,10 +419,10 @@ the default timeout and poll interval values. This can be done as follows:
|
|||
// Swift
|
||||
|
||||
// Increase the global timeout to 5 seconds:
|
||||
Nimble.AsyncDefaults.Timeout = 5
|
||||
Nimble.AsyncDefaults.timeout = .seconds(1)
|
||||
|
||||
// Slow the polling interval to 0.1 seconds:
|
||||
Nimble.AsyncDefaults.PollInterval = 0.1
|
||||
Nimble.AsyncDefaults.pollInterval = .milliseconds(100)
|
||||
```
|
||||
|
||||
## Objective-C Support
|
||||
|
@ -1171,20 +1172,31 @@ For Objective-C, the actual value must be one of the following classes, or their
|
|||
|
||||
```swift
|
||||
// Swift
|
||||
let testNotification = Notification(name: "Foo", object: nil)
|
||||
let testNotification = Notification(name: Notification.Name("Foo"), object: nil)
|
||||
|
||||
// passes if the closure in expect { ... } posts a notification to the default
|
||||
// Passes if the closure in expect { ... } posts a notification to the default
|
||||
// notification center.
|
||||
expect {
|
||||
NotificationCenter.default.postNotification(testNotification)
|
||||
}.to(postNotifications(equal([testNotification]))
|
||||
NotificationCenter.default.post(testNotification)
|
||||
}.to(postNotifications(equal([testNotification])))
|
||||
|
||||
// passes if the closure in expect { ... } posts a notification to a given
|
||||
// Passes if the closure in expect { ... } posts a notification to a given
|
||||
// notification center
|
||||
let notificationCenter = NotificationCenter()
|
||||
expect {
|
||||
notificationCenter.postNotification(testNotification)
|
||||
}.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter))
|
||||
notificationCenter.post(testNotification)
|
||||
}.to(postNotifications(equal([testNotification]), from: notificationCenter))
|
||||
|
||||
// Passes if the closure in expect { ... } posts a notification with the provided names to a given
|
||||
// notification center. Make sure to use this when running tests on Catalina,
|
||||
// using DistributedNotificationCenter as there is currently no way
|
||||
// of observing notifications without providing specific names.
|
||||
let distributedNotificationCenter = DistributedNotificationCenter()
|
||||
expect {
|
||||
distributedNotificationCenter.post(testNotification)
|
||||
}.toEventually(postDistributedNotifications(equal([testNotification]),
|
||||
from: distributedNotificationCenter,
|
||||
names: [testNotification.name]))
|
||||
```
|
||||
|
||||
> This matcher is only available in Swift.
|
||||
|
@ -1503,19 +1515,17 @@ For a more comprehensive message that spans multiple lines, use
|
|||
## Supporting Objective-C
|
||||
|
||||
To use a custom matcher written in Swift from Objective-C, you'll have
|
||||
to extend the `NMBObjCMatcher` class, adding a new class method for your
|
||||
to extend the `NMBPredicate` class, adding a new class method for your
|
||||
custom matcher. The example below defines the class method
|
||||
`+[NMBObjCMatcher beNilMatcher]`:
|
||||
`+[NMBPredicate beNilMatcher]`:
|
||||
|
||||
```swift
|
||||
// Swift
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beNilMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualBlock, failureMessage, location in
|
||||
let block = ({ actualBlock() as NSObject? })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
return beNil().matches(expr, failureMessage: failureMessage)
|
||||
extension NMBPredicate {
|
||||
@objc public class func beNilMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beNil().satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1526,7 +1536,7 @@ The above allows you to use the matcher from Objective-C:
|
|||
```objc
|
||||
// Objective-C
|
||||
|
||||
expect(actual).to([NMBObjCMatcher beNilMatcher]());
|
||||
expect(actual).to([NMBPredicate beNilMatcher]());
|
||||
```
|
||||
|
||||
To make the syntax easier to use, define a C function that calls the
|
||||
|
@ -1535,8 +1545,8 @@ class method:
|
|||
```objc
|
||||
// Objective-C
|
||||
|
||||
FOUNDATION_EXPORT id<NMBMatcher> beNil() {
|
||||
return [NMBObjCMatcher beNilMatcher];
|
||||
FOUNDATION_EXPORT NMBPredicate *beNil() {
|
||||
return [NMBPredicate beNilMatcher];
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1558,29 +1568,25 @@ expect(nil).to(equal(nil)); // fails
|
|||
expect(nil).to(beNil()); // passes
|
||||
```
|
||||
|
||||
If your matcher does not want to match with nil, you use `NonNilMatcherFunc`
|
||||
and the `canMatchNil` constructor on `NMBObjCMatcher`. Using both types will
|
||||
automatically generate expected value failure messages when they're nil.
|
||||
If your matcher does not want to match with nil, you use `Predicate.define` or `Predicate.simple`.
|
||||
Using those factory methods will automatically generate expected value failure messages when they're nil.
|
||||
|
||||
```swift
|
||||
public func beginWith<S: Sequence>(_ startingElement: S.Element) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("begin with <\(startingElement)>") { actualExpression in
|
||||
guard let actualValue = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
public func beginWith<S: Sequence, T: Equatable where S.Iterator.Element == T>(startingElement: T) -> NonNilMatcherFunc<S> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingElement)>"
|
||||
if let actualValue = actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
return actualGenerator.next() == startingElement
|
||||
}
|
||||
return false
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
return PredicateStatus(bool: actualGenerator.next() == startingElement)
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
let actual = actualExpression.evaluate()
|
||||
extension NMBPredicate {
|
||||
@objc public class func beginWithMatcher(_ expected: Any) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
|
||||
return beginWith(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beginWith(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1605,7 +1611,7 @@ converts those types to the newer `Predicate`.
|
|||
|
||||
```swift
|
||||
// Swift
|
||||
public func beginWith<S: Sequence, T: Equatable where S.Iterator.Element == T>(startingElement: T) -> Predicate<S> {
|
||||
public func beginWith<S: Sequence>(_ startingElement: S.Element) -> Predicate<S> where S.Element: Equatable {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingElement)>"
|
||||
if let actualValue = actualExpression.evaluate() {
|
||||
|
@ -1628,7 +1634,7 @@ matcher types.
|
|||
|
||||
```swift
|
||||
// Swift
|
||||
public func beginWith<S: Sequence, T: Equatable where S.Iterator.Element == T>(startingElement: T) -> Predicate<S> {
|
||||
public func beginWith<S: Sequence>(_ startingElement: S.Element) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingElement)>"
|
||||
if let actualValue = actualExpression.evaluate() {
|
||||
|
@ -1705,12 +1711,33 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||
|
||||
target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do
|
||||
use_frameworks!
|
||||
pod 'Nimble', '~> 6.0.0'
|
||||
pod 'Nimble'
|
||||
end
|
||||
```
|
||||
|
||||
Finally run `pod install`.
|
||||
|
||||
## Installing Nimble via Accio
|
||||
|
||||
Add the following to your Package.swift:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/Quick/Nimble.git", .upToNextMajor(from: "8.0.1")),
|
||||
```
|
||||
|
||||
Next, add `Nimble` to your App targets dependencies like so:
|
||||
|
||||
```swift
|
||||
.testTarget(
|
||||
name: "AppTests",
|
||||
dependencies: [
|
||||
"Nimble",
|
||||
]
|
||||
),
|
||||
```
|
||||
|
||||
Then run `accio update`.
|
||||
|
||||
## Using Nimble without XCTest
|
||||
|
||||
Nimble is integrated with XCTest to allow it work well when used in Xcode test
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// Protocol for the assertion handler that Nimble uses for all expectations.
|
||||
public protocol AssertionHandler {
|
||||
func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A data structure that stores information about an assertion when
|
||||
/// AssertionRecorder is set as the Nimble assertion handler.
|
||||
///
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
import class Foundation.NSObject
|
||||
import typealias Foundation.TimeInterval
|
||||
import enum Dispatch.DispatchTimeInterval
|
||||
|
||||
private func from(objcPredicate: NMBPredicate) -> Predicate<NSObject> {
|
||||
return Predicate { actualExpression in
|
||||
|
@ -10,24 +11,27 @@ private func from(objcPredicate: NMBPredicate) -> Predicate<NSObject> {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct ObjCMatcherWrapper: Matcher {
|
||||
let matcher: NMBMatcher
|
||||
|
||||
func matches(_ actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! actualExpression.evaluate() }),
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location)
|
||||
}
|
||||
|
||||
func doesNotMatch(_ actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.doesNotMatch(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! actualExpression.evaluate() }),
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location)
|
||||
private func from(matcher: NMBMatcher, style: ExpectationStyle) -> Predicate<NSObject> {
|
||||
// Almost same as `Matcher.toClosure`
|
||||
let closure: (Expression<NSObject>, FailureMessage) throws -> Bool = { expr, msg in
|
||||
switch style {
|
||||
case .toMatch:
|
||||
return matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! expr.evaluate() }),
|
||||
failureMessage: msg,
|
||||
location: expr.location
|
||||
)
|
||||
case .toNotMatch:
|
||||
return !matcher.doesNotMatch(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! expr.evaluate() }),
|
||||
failureMessage: msg,
|
||||
location: expr.location
|
||||
)
|
||||
}
|
||||
}
|
||||
return Predicate._fromDeprecatedClosure(closure)
|
||||
}
|
||||
|
||||
// Equivalent to Expectation, but for Nimble's Objective-C interface
|
||||
|
@ -37,7 +41,7 @@ public class NMBExpectation: NSObject {
|
|||
internal var _negative: Bool
|
||||
internal let _file: FileString
|
||||
internal let _line: UInt
|
||||
internal var _timeout: TimeInterval = 1.0
|
||||
internal var _timeout: DispatchTimeInterval = .seconds(1)
|
||||
// swiftlint:enable identifier_name
|
||||
|
||||
@objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) {
|
||||
|
@ -48,63 +52,65 @@ public class NMBExpectation: NSObject {
|
|||
}
|
||||
|
||||
private var expectValue: Expectation<NSObject> {
|
||||
return expect(_file, line: _line) {
|
||||
self._actualBlock() as NSObject?
|
||||
}
|
||||
return expect(file: _file, line: _line, self._actualBlock() as NSObject?)
|
||||
}
|
||||
|
||||
@objc public var withTimeout: (TimeInterval) -> NMBExpectation {
|
||||
return ({ timeout in self._timeout = timeout
|
||||
return { timeout in self._timeout = timeout.dispatchInterval
|
||||
return self
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var to: (NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
@objc public var to: (NMBMatcher) -> NMBExpectation {
|
||||
return { matcher in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.to(from(objcPredicate: pred))
|
||||
} else {
|
||||
self.expectValue.to(ObjCMatcherWrapper(matcher: matcher))
|
||||
self.expectValue.to(from(matcher: matcher, style: .toMatch))
|
||||
}
|
||||
})
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toWithDescription: (NMBMatcher, String) -> Void {
|
||||
return ({ matcher, description in
|
||||
@objc public var toWithDescription: (NMBMatcher, String) -> NMBExpectation {
|
||||
return { matcher, description in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.to(from(objcPredicate: pred), description: description)
|
||||
} else {
|
||||
self.expectValue.to(ObjCMatcherWrapper(matcher: matcher), description: description)
|
||||
self.expectValue.to(from(matcher: matcher, style: .toMatch), description: description)
|
||||
}
|
||||
})
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toNot: (NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
@objc public var toNot: (NMBMatcher) -> NMBExpectation {
|
||||
return { matcher in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toNot(from(objcPredicate: pred))
|
||||
} else {
|
||||
self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher))
|
||||
self.expectValue.toNot(from(matcher: matcher, style: .toNotMatch))
|
||||
}
|
||||
})
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toNotWithDescription: (NMBMatcher, String) -> Void {
|
||||
return ({ matcher, description in
|
||||
@objc public var toNotWithDescription: (NMBMatcher, String) -> NMBExpectation {
|
||||
return { matcher, description in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toNot(from(objcPredicate: pred), description: description)
|
||||
} else {
|
||||
self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher), description: description)
|
||||
self.expectValue.toNot(from(matcher: matcher, style: .toNotMatch), description: description)
|
||||
}
|
||||
})
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var notTo: (NMBMatcher) -> Void { return toNot }
|
||||
@objc public var notTo: (NMBMatcher) -> NMBExpectation { return toNot }
|
||||
|
||||
@objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription }
|
||||
@objc public var notToWithDescription: (NMBMatcher, String) -> NMBExpectation { return toNotWithDescription }
|
||||
|
||||
@objc public var toEventually: (NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
return { matcher in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toEventually(
|
||||
from(objcPredicate: pred),
|
||||
|
@ -113,16 +119,16 @@ public class NMBExpectation: NSObject {
|
|||
)
|
||||
} else {
|
||||
self.expectValue.toEventually(
|
||||
ObjCMatcherWrapper(matcher: matcher),
|
||||
from(matcher: matcher, style: .toMatch),
|
||||
timeout: self._timeout,
|
||||
description: nil
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void {
|
||||
return ({ matcher, description in
|
||||
return { matcher, description in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toEventually(
|
||||
from(objcPredicate: pred),
|
||||
|
@ -131,16 +137,16 @@ public class NMBExpectation: NSObject {
|
|||
)
|
||||
} else {
|
||||
self.expectValue.toEventually(
|
||||
ObjCMatcherWrapper(matcher: matcher),
|
||||
from(matcher: matcher, style: .toMatch),
|
||||
timeout: self._timeout,
|
||||
description: description
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toEventuallyNot: (NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
return { matcher in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toEventuallyNot(
|
||||
from(objcPredicate: pred),
|
||||
|
@ -149,16 +155,16 @@ public class NMBExpectation: NSObject {
|
|||
)
|
||||
} else {
|
||||
self.expectValue.toEventuallyNot(
|
||||
ObjCMatcherWrapper(matcher: matcher),
|
||||
from(matcher: matcher, style: .toNotMatch),
|
||||
timeout: self._timeout,
|
||||
description: nil
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void {
|
||||
return ({ matcher, description in
|
||||
return { matcher, description in
|
||||
if let pred = matcher as? NMBPredicate {
|
||||
self.expectValue.toEventuallyNot(
|
||||
from(objcPredicate: pred),
|
||||
|
@ -167,12 +173,12 @@ public class NMBExpectation: NSObject {
|
|||
)
|
||||
} else {
|
||||
self.expectValue.toEventuallyNot(
|
||||
ObjCMatcherWrapper(matcher: matcher),
|
||||
from(matcher: matcher, style: .toNotMatch),
|
||||
timeout: self._timeout,
|
||||
description: description
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var toNotEventually: (NMBMatcher) -> Void {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import Foundation
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSObject
|
||||
|
||||
// swiftlint:disable line_length
|
||||
public typealias MatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage) throws -> Bool
|
||||
public typealias FullMatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool
|
||||
// swiftlint:enable line_length
|
||||
|
||||
@available(*, deprecated, message: "Use NMBPredicate instead")
|
||||
public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
let _match: MatcherBlock
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Dispatch
|
||||
import Foundation
|
||||
import class Foundation.NSObject
|
||||
import class Foundation.Thread
|
||||
|
||||
/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this
|
||||
/// class' existence
|
||||
|
|
|
@ -45,7 +45,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler {
|
|||
private var stashed_swift_reportFatalErrorsToDebugger: Bool = false
|
||||
|
||||
@objc func testCaseWillStart(_ testCase: XCTestCase) {
|
||||
#if swift(>=3.2)
|
||||
#if os(macOS) || os(iOS)
|
||||
stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger
|
||||
_swift_reportFatalErrorsToDebugger = false
|
||||
#endif
|
||||
|
@ -56,7 +56,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler {
|
|||
@objc func testCaseDidFinish(_ testCase: XCTestCase) {
|
||||
currentTestCase = nil
|
||||
|
||||
#if swift(>=3.2)
|
||||
#if os(macOS) || os(iOS)
|
||||
_swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Foundation
|
||||
|
||||
#if !canImport(Darwin)
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSException
|
||||
#else
|
||||
// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy
|
||||
class NSException {}
|
||||
#endif
|
||||
|
|
|
@ -21,13 +21,13 @@ internal class NMBWait: NSObject {
|
|||
file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
return throwableUntil(timeout: timeout, file: file, line: line) { done in
|
||||
action(done)
|
||||
}
|
||||
// Convert TimeInterval to DispatchTimeInterval
|
||||
until(timeout: timeout.dispatchInterval, file: file, line: line, action: action)
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
internal class func until(
|
||||
timeout: TimeInterval,
|
||||
timeout: DispatchTimeInterval,
|
||||
file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
|
@ -35,16 +35,15 @@ internal class NMBWait: NSObject {
|
|||
action(done)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Using a throwable closure makes this method not objc compatible.
|
||||
internal class func throwableUntil(
|
||||
timeout: TimeInterval,
|
||||
timeout: DispatchTimeInterval,
|
||||
file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) throws -> Void) {
|
||||
let awaiter = NimbleEnvironment.activeInstance.awaiter
|
||||
let leeway = timeout / 2.0
|
||||
let leeway = timeout.divided
|
||||
// swiftlint:disable:next line_length
|
||||
let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in
|
||||
DispatchQueue.main.async {
|
||||
|
@ -72,8 +71,7 @@ internal class NMBWait: NSObject {
|
|||
fail(blockedRunLoopErrorMessageFor("-waitUntil()", leeway: leeway),
|
||||
file: file, line: line)
|
||||
case .timedOut:
|
||||
let pluralize = (timeout == 1 ? "" : "s")
|
||||
fail("Waited more than \(timeout) second\(pluralize)", file: file, line: line)
|
||||
fail("Waited more than \(timeout.description)", file: file, line: line)
|
||||
case let .raisedException(exception):
|
||||
fail("Unexpected exception raised: \(exception)")
|
||||
case let .errorThrown(error):
|
||||
|
@ -93,21 +91,21 @@ internal class NMBWait: NSObject {
|
|||
_ file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
until(timeout: 1, file: file, line: line, action: action)
|
||||
until(timeout: .seconds(1), file: file, line: line, action: action)
|
||||
}
|
||||
#else
|
||||
internal class func until(
|
||||
_ file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
until(timeout: 1, file: file, line: line, action: action)
|
||||
until(timeout: .seconds(1), file: file, line: line, action: action)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String {
|
||||
internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: DispatchTimeInterval) -> String {
|
||||
// swiftlint:disable:next line_length
|
||||
return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway) seconds is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run."
|
||||
return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway.description) is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run."
|
||||
}
|
||||
|
||||
/// Wait asynchronously until the done closure is called or the timeout has been reached.
|
||||
|
@ -117,6 +115,6 @@ internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterv
|
|||
///
|
||||
/// 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: TimeInterval = AsyncDefaults.Timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) {
|
||||
public func waitUntil(timeout: DispatchTimeInterval = AsyncDefaults.timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) {
|
||||
NMBWait.until(timeout: timeout, file: file, line: line, action: action)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Foundation
|
||||
|
||||
/// Make an expectation on a given actual value. The value given is lazily evaluated.
|
||||
public func expect<T>(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation<T> {
|
||||
public func expect<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure @escaping () throws -> T?) -> Expectation<T> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression,
|
||||
|
@ -10,10 +8,28 @@ public func expect<T>(_ expression: @autoclosure @escaping () throws -> T?, file
|
|||
}
|
||||
|
||||
/// Make an expectation on a given actual value. The closure is lazily invoked.
|
||||
public func expect<T>(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation<T> {
|
||||
public func expect<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() throws -> T)) -> Expectation<T> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression,
|
||||
expression: expression(),
|
||||
location: SourceLocation(file: file, line: line),
|
||||
isClosure: true))
|
||||
}
|
||||
|
||||
/// Make an expectation on a given actual value. The closure is lazily invoked.
|
||||
public func expect<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() throws -> T?)) -> Expectation<T> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression(),
|
||||
location: SourceLocation(file: file, line: line),
|
||||
isClosure: true))
|
||||
}
|
||||
|
||||
/// Make an expectation on a given actual value. The closure is lazily invoked.
|
||||
public func expect(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() throws -> Void)) -> Expectation<Void> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression(),
|
||||
location: SourceLocation(file: file, line: line),
|
||||
isClosure: true))
|
||||
}
|
||||
|
@ -36,24 +52,16 @@ public func fail(_ file: FileString = #file, line: UInt = #line) {
|
|||
|
||||
/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts
|
||||
internal func nimblePrecondition(
|
||||
_ expr: @autoclosure() -> Bool,
|
||||
_ name: @autoclosure() -> String,
|
||||
_ message: @autoclosure() -> String,
|
||||
_ expr: @autoclosure () -> Bool,
|
||||
_ name: @autoclosure () -> String,
|
||||
_ message: @autoclosure () -> String,
|
||||
file: StaticString = #file,
|
||||
line: UInt = #line) {
|
||||
let result = expr()
|
||||
if !result {
|
||||
#if canImport(Darwin)
|
||||
let exception = NSException(
|
||||
name: NSExceptionName(name()),
|
||||
reason: message(),
|
||||
userInfo: nil
|
||||
)
|
||||
exception.raise()
|
||||
#else
|
||||
preconditionFailure("\(name()) - \(message())", file: file, line: line)
|
||||
#endif
|
||||
}
|
||||
line: UInt = #line
|
||||
) {
|
||||
let result = expr()
|
||||
if !result {
|
||||
_nimblePrecondition(name(), message(), file, line)
|
||||
}
|
||||
}
|
||||
|
||||
internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never {
|
||||
|
@ -66,3 +74,31 @@ internal func internalError(_ msg: String, file: FileString = #file, line: UInt
|
|||
)
|
||||
// swiftlint:enable line_length
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSException
|
||||
import struct Foundation.NSExceptionName
|
||||
|
||||
private func _nimblePrecondition(
|
||||
_ name: String,
|
||||
_ message: String,
|
||||
_ file: StaticString,
|
||||
_ line: UInt
|
||||
) {
|
||||
let exception = NSException(
|
||||
name: NSExceptionName(name),
|
||||
reason: message,
|
||||
userInfo: nil
|
||||
)
|
||||
exception.raise()
|
||||
}
|
||||
#else
|
||||
private func _nimblePrecondition(
|
||||
_ name: String,
|
||||
_ message: String,
|
||||
_ file: StaticString,
|
||||
_ line: UInt
|
||||
) {
|
||||
preconditionFailure("\(name) - \(message)", file: file, line: line)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import Foundation
|
||||
|
||||
// Deprecated
|
||||
@available(*, deprecated)
|
||||
internal func expressionDoesNotMatch<T, U>(_ expression: Expression<T>, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
let msg = FailureMessage()
|
||||
|
@ -69,7 +67,9 @@ public struct Expectation<T> {
|
|||
////////////////// OLD API /////////////////////
|
||||
|
||||
/// DEPRECATED: Tests the actual value using a matcher to match.
|
||||
public func to<U>(_ matcher: U, description: String? = nil)
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
@discardableResult
|
||||
public func to<U>(_ matcher: U, description: String? = nil) -> Self
|
||||
where U: Matcher, U.ValueType == T {
|
||||
let (pass, msg) = execute(
|
||||
expression,
|
||||
|
@ -80,43 +80,54 @@ public struct Expectation<T> {
|
|||
captureExceptions: false
|
||||
)
|
||||
verify(pass, msg)
|
||||
return self
|
||||
}
|
||||
|
||||
/// DEPRECATED: Tests the actual value using a matcher to not match.
|
||||
public func toNot<U>(_ matcher: U, description: String? = nil)
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
@discardableResult
|
||||
public func toNot<U>(_ matcher: U, description: String? = nil) -> Self
|
||||
where U: Matcher, U.ValueType == T {
|
||||
// swiftlint:disable:next line_length
|
||||
let (pass, msg) = expressionDoesNotMatch(expression, matcher: matcher, toNot: "to not", description: description)
|
||||
verify(pass, msg)
|
||||
return self
|
||||
}
|
||||
|
||||
/// DEPRECATED: Tests the actual value using a matcher to not match.
|
||||
///
|
||||
/// Alias to toNot().
|
||||
public func notTo<U>(_ matcher: U, description: String? = nil)
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
@discardableResult
|
||||
public func notTo<U>(_ matcher: U, description: String? = nil) -> Self
|
||||
where U: Matcher, U.ValueType == T {
|
||||
toNot(matcher, description: description)
|
||||
return toNot(matcher, description: description)
|
||||
}
|
||||
|
||||
////////////////// NEW API /////////////////////
|
||||
|
||||
/// Tests the actual value using a matcher to match.
|
||||
public func to(_ predicate: Predicate<T>, description: String? = nil) {
|
||||
@discardableResult
|
||||
public func to(_ predicate: Predicate<T>, description: String? = nil) -> Self {
|
||||
let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description)
|
||||
verify(pass, msg)
|
||||
return self
|
||||
}
|
||||
|
||||
/// Tests the actual value using a matcher to not match.
|
||||
public func toNot(_ predicate: Predicate<T>, description: String? = nil) {
|
||||
@discardableResult
|
||||
public func toNot(_ predicate: Predicate<T>, description: String? = nil) -> Self {
|
||||
let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description)
|
||||
verify(pass, msg)
|
||||
return self
|
||||
}
|
||||
|
||||
/// Tests the actual value using a matcher to not match.
|
||||
///
|
||||
/// Alias to toNot().
|
||||
public func notTo(_ predicate: Predicate<T>, description: String? = nil) {
|
||||
toNot(predicate, description: description)
|
||||
@discardableResult
|
||||
public func notTo(_ predicate: Predicate<T>, description: String? = nil) -> Self {
|
||||
return toNot(predicate, description: description)
|
||||
}
|
||||
|
||||
// see:
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import Foundation
|
||||
|
||||
public indirect enum ExpectationMessage {
|
||||
// --- Primary Expectations ---
|
||||
/// includes actual value in output ("expected to <message>, got <actual>")
|
||||
case expectedActualValueTo(/* message: */ String)
|
||||
/// uses a custom actual value string in output ("expected to <message>, got <actual>")
|
||||
case expectedCustomValueTo(/* message: */ String, /* actual: */ String)
|
||||
case expectedCustomValueTo(/* message: */ String, actual: String)
|
||||
/// excludes actual value in output ("expected to <message>")
|
||||
case expectedTo(/* message: */ String)
|
||||
/// allows any free-form message ("<message>")
|
||||
|
@ -23,14 +21,6 @@ public indirect enum ExpectationMessage {
|
|||
/// provides long-form multi-line explainations ("<expectation>\n\n<string>")
|
||||
case details(ExpectationMessage, String)
|
||||
|
||||
internal var sampleMessage: String {
|
||||
let asStr = toString(actual: "<ACTUAL>", expected: "expected", to: "to")
|
||||
let asFailureMessage = FailureMessage()
|
||||
update(failureMessage: asFailureMessage)
|
||||
// swiftlint:disable:next line_length
|
||||
return "(toString(actual:expected:to:) -> \(asStr) || update(failureMessage:) -> \(asFailureMessage.stringValue))"
|
||||
}
|
||||
|
||||
/// Returns the smallest message after the "expected to" string that summarizes the error.
|
||||
///
|
||||
/// Returns the message part from ExpectationMessage, ignoring all .appends and .details.
|
||||
|
@ -118,7 +108,7 @@ public indirect enum ExpectationMessage {
|
|||
case let .expectedActualValueTo(msg):
|
||||
return .expectedActualValueTo(message + msg)
|
||||
case let .expectedCustomValueTo(msg, actual):
|
||||
return .expectedCustomValueTo(message + msg, actual)
|
||||
return .expectedCustomValueTo(message + msg, actual: actual)
|
||||
default:
|
||||
return msg.visitLeafs(walk)
|
||||
}
|
||||
|
@ -193,7 +183,7 @@ extension FailureMessage {
|
|||
|
||||
var message: ExpectationMessage = .fail(userDescription ?? "")
|
||||
if actualValue != "" && actualValue != nil {
|
||||
message = .expectedCustomValueTo(postfixMessage, actualValue ?? "")
|
||||
message = .expectedCustomValueTo(postfixMessage, actual: actualValue ?? "")
|
||||
} else if postfixMessage != defaultMessage.postfixMessage {
|
||||
if actualValue == nil {
|
||||
message = .expectedTo(postfixMessage)
|
||||
|
@ -212,6 +202,7 @@ extension FailureMessage {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSObject
|
||||
|
||||
public class NMBExpectationMessage: NSObject {
|
||||
private let msg: ExpectationMessage
|
||||
|
@ -228,7 +219,7 @@ public class NMBExpectationMessage: NSObject {
|
|||
}
|
||||
|
||||
public init(expectedActualValueTo message: String, customActualValue actual: String) {
|
||||
self.msg = .expectedCustomValueTo(message, actual)
|
||||
self.msg = .expectedCustomValueTo(message, actual: actual)
|
||||
}
|
||||
|
||||
public init(fail message: String) {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import Foundation
|
||||
|
||||
// Memoizes the given closure, only calling the passed
|
||||
// closure once; even if repeat calls to the returned closure
|
||||
internal func memoizedClosure<T>(_ closure: @escaping () throws -> T) -> (Bool) throws -> T {
|
||||
var cache: T?
|
||||
return ({ withoutCaching in
|
||||
return { withoutCaching in
|
||||
if withoutCaching || cache == nil {
|
||||
cache = try closure()
|
||||
}
|
||||
return cache!
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Expression represents the closure of the value inside expect(...).
|
||||
|
|
|
@ -1,70 +1,71 @@
|
|||
import Foundation
|
||||
public func allPass<S: Sequence>(
|
||||
_ passFunc: @escaping (S.Element?) throws -> Bool
|
||||
) -> Predicate<S> {
|
||||
let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in
|
||||
return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
|
||||
}
|
||||
return createPredicate(matcher)
|
||||
}
|
||||
|
||||
public func allPass<T, U>
|
||||
(_ passFunc: @escaping (T?) throws -> Bool) -> Predicate<U>
|
||||
where U: Sequence, T == U.Iterator.Element {
|
||||
let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in
|
||||
return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
|
||||
public func allPass<S: Sequence>(
|
||||
_ passName: String,
|
||||
_ passFunc: @escaping (S.Element?) throws -> Bool
|
||||
) -> Predicate<S> {
|
||||
let matcher = Predicate.simpleNilable(passName) { actualExpression in
|
||||
return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
|
||||
}
|
||||
return createPredicate(matcher)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func allPass<S: Sequence, M: Matcher>(_ elementMatcher: M) -> Predicate<S> where S.Element == M.ValueType {
|
||||
return createPredicate(elementMatcher.predicate)
|
||||
}
|
||||
|
||||
public func allPass<S: Sequence>(_ elementPredicate: Predicate<S.Element>) -> Predicate<S> {
|
||||
return createPredicate(elementPredicate)
|
||||
}
|
||||
|
||||
private func createPredicate<S: Sequence>(_ elementMatcher: Predicate<S.Element>) -> Predicate<S> {
|
||||
return Predicate { actualExpression in
|
||||
guard let actualValue = try actualExpression.evaluate() else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: .appends(.expectedTo("all pass"), " (use beNil() to match nils)")
|
||||
)
|
||||
}
|
||||
return createPredicate(matcher)
|
||||
}
|
||||
|
||||
public func allPass<T, U>
|
||||
(_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate<U>
|
||||
where U: Sequence, T == U.Iterator.Element {
|
||||
let matcher = Predicate.simpleNilable(passName) { actualExpression in
|
||||
return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
|
||||
}
|
||||
return createPredicate(matcher)
|
||||
}
|
||||
|
||||
public func allPass<S, M>(_ elementMatcher: M) -> Predicate<S>
|
||||
where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType {
|
||||
return createPredicate(elementMatcher.predicate)
|
||||
}
|
||||
|
||||
public func allPass<S>(_ elementPredicate: Predicate<S.Iterator.Element>) -> Predicate<S>
|
||||
where S: Sequence {
|
||||
return createPredicate(elementPredicate)
|
||||
}
|
||||
|
||||
private func createPredicate<S>(_ elementMatcher: Predicate<S.Iterator.Element>) -> Predicate<S>
|
||||
where S: Sequence {
|
||||
return Predicate { actualExpression in
|
||||
guard let actualValue = try actualExpression.evaluate() else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: .appends(.expectedTo("all pass"), " (use beNil() to match nils)")
|
||||
var failure: ExpectationMessage = .expectedTo("all pass")
|
||||
for currentElement in actualValue {
|
||||
let exp = Expression(
|
||||
expression: {currentElement}, location: actualExpression.location)
|
||||
let predicateResult = try elementMatcher.satisfies(exp)
|
||||
if predicateResult.status == .matches {
|
||||
failure = predicateResult.message.prepended(expectation: "all ")
|
||||
} else {
|
||||
failure = predicateResult.message
|
||||
.replacedExpectation({ .expectedTo($0.expectedMessage) })
|
||||
.wrappedExpectation(
|
||||
before: "all ",
|
||||
after: ", but failed first at element <\(stringify(currentElement))>"
|
||||
+ " in <\(stringify(actualValue))>"
|
||||
)
|
||||
return PredicateResult(status: .doesNotMatch, message: failure)
|
||||
}
|
||||
|
||||
var failure: ExpectationMessage = .expectedTo("all pass")
|
||||
for currentElement in actualValue {
|
||||
let exp = Expression(
|
||||
expression: {currentElement}, location: actualExpression.location)
|
||||
let predicateResult = try elementMatcher.satisfies(exp)
|
||||
if predicateResult.status == .matches {
|
||||
failure = predicateResult.message.prepended(expectation: "all ")
|
||||
} else {
|
||||
failure = predicateResult.message
|
||||
.replacedExpectation({ .expectedTo($0.expectedMessage) })
|
||||
.wrappedExpectation(
|
||||
before: "all ",
|
||||
after: ", but failed first at element <\(stringify(currentElement))>"
|
||||
+ " in <\(stringify(actualValue))>"
|
||||
)
|
||||
return PredicateResult(status: .doesNotMatch, message: failure)
|
||||
}
|
||||
}
|
||||
failure = failure.replacedExpectation({ expectation in
|
||||
return .expectedTo(expectation.expectedMessage)
|
||||
})
|
||||
return PredicateResult(status: .matches, message: failure)
|
||||
}
|
||||
failure = failure.replacedExpectation({ expectation in
|
||||
return .expectedTo(expectation.expectedMessage)
|
||||
})
|
||||
return PredicateResult(status: .matches, message: failure)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
import class Foundation.NSObject
|
||||
import struct Foundation.NSFastEnumerationIterator
|
||||
import protocol Foundation.NSFastEnumeration
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
import Foundation
|
||||
import Dispatch
|
||||
|
||||
/// If you are running on a slower machine, it could be useful to increase the default timeout value
|
||||
/// or slow down poll interval. Default timeout interval is 1, and poll interval is 0.01.
|
||||
public struct AsyncDefaults {
|
||||
public static var timeout: DispatchTimeInterval = .seconds(1)
|
||||
public static var pollInterval: DispatchTimeInterval = .milliseconds(10)
|
||||
}
|
||||
|
||||
extension AsyncDefaults {
|
||||
@available(*, unavailable, renamed: "timeout")
|
||||
public static var Timeout: TimeInterval = 1
|
||||
@available(*, unavailable, renamed: "pollInterval")
|
||||
public static var PollInterval: TimeInterval = 0.01
|
||||
}
|
||||
|
||||
private func async<T>(style: ExpectationStyle, predicate: Predicate<T>, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate<T> {
|
||||
private func async<T>(style: ExpectationStyle, predicate: Predicate<T>, timeout: DispatchTimeInterval, poll: DispatchTimeInterval, fnName: String) -> Predicate<T> {
|
||||
return Predicate { actualExpression in
|
||||
let uncachedExpression = actualExpression.withoutCaching()
|
||||
let fnName = "expect(...).\(fnName)(...)"
|
||||
|
@ -55,7 +63,7 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toEventually(_ predicate: Predicate<T>, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) {
|
||||
public func toEventually(_ predicate: Predicate<T>, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil) {
|
||||
nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue)
|
||||
|
||||
let (pass, msg) = execute(
|
||||
|
@ -75,7 +83,7 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toEventuallyNot(_ predicate: Predicate<T>, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) {
|
||||
public func toEventuallyNot(_ predicate: Predicate<T>, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil) {
|
||||
nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue)
|
||||
|
||||
let (pass, msg) = execute(
|
||||
|
@ -103,12 +111,12 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toNotEventually(_ predicate: Predicate<T>, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) {
|
||||
public func toNotEventually(_ predicate: Predicate<T>, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil) {
|
||||
return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
extension Expectation {
|
||||
/// Tests the actual value using a matcher to match by checking continuously
|
||||
/// at each pollInterval until the timeout is reached.
|
||||
|
@ -116,7 +124,7 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toEventually<U>(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil)
|
||||
public func toEventually<U>(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
if expression.isClosure {
|
||||
let (pass, msg) = execute(
|
||||
|
@ -145,7 +153,7 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toEventuallyNot<U>(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil)
|
||||
public func toEventuallyNot<U>(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
if expression.isClosure {
|
||||
let (pass, msg) = expressionDoesNotMatch(
|
||||
|
@ -174,7 +182,7 @@ extension Expectation {
|
|||
/// @discussion
|
||||
/// 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 toNotEventually<U>(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil)
|
||||
public func toNotEventually<U>(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.pollInterval, description: String? = nil)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
private func matcherMessage<T>(forType expectedType: T.Type) -> String {
|
||||
return "be a kind of \(String(describing: expectedType))"
|
||||
}
|
||||
|
@ -14,12 +12,12 @@ public func beAKindOf<T>(_ expectedType: T.Type) -> Predicate<Any> {
|
|||
|
||||
let instance = try actualExpression.evaluate()
|
||||
guard let validInstance = instance else {
|
||||
message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "<nil>")
|
||||
message = .expectedCustomValueTo(matcherMessage(forType: expectedType), actual: "<nil>")
|
||||
return PredicateResult(status: .fail, message: message)
|
||||
}
|
||||
message = .expectedCustomValueTo(
|
||||
"be a kind of \(String(describing: expectedType))",
|
||||
"<\(String(describing: type(of: validInstance))) instance>"
|
||||
actual: "<\(String(describing: type(of: validInstance))) instance>"
|
||||
)
|
||||
|
||||
return PredicateResult(
|
||||
|
@ -30,6 +28,7 @@ public func beAKindOf<T>(_ expectedType: T.Type) -> Predicate<Any> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSObject
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is an instance of the given class.
|
||||
/// @see beAnInstanceOf if you want to match against the exact class
|
||||
|
@ -43,13 +42,13 @@ public func beAKindOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
|||
status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass))
|
||||
message = .expectedCustomValueTo(
|
||||
matcherMessage(forClass: expectedClass),
|
||||
"<\(String(describing: type(of: validInstance))) instance>"
|
||||
actual: "<\(String(describing: type(of: validInstance))) instance>"
|
||||
)
|
||||
} else {
|
||||
status = .fail
|
||||
message = .expectedCustomValueTo(
|
||||
matcherMessage(forClass: expectedClass),
|
||||
"<nil>"
|
||||
actual: "<nil>"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -57,8 +56,8 @@ public func beAKindOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
|||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public func beAnInstanceOf<T>(_ expectedType: T.Type) -> Predicate<Any> {
|
|||
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: type(of: validInstance) == expectedType),
|
||||
message: .expectedCustomValueTo(errorMessage, actualString)
|
||||
message: .expectedCustomValueTo(errorMessage, actual: actualString)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -40,14 +40,14 @@ public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
|||
#endif
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: matches),
|
||||
message: .expectedCustomValueTo(errorMessage, actualString)
|
||||
message: .expectedCustomValueTo(errorMessage, actual: actualString)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ internal func isCloseTo(_ actualValue: NMBDoubleConvertible?,
|
|||
return PredicateResult(
|
||||
bool: actualValue != nil &&
|
||||
abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta,
|
||||
message: .expectedCustomValueTo(errorMessage, "<\(stringify(actualValue))>")
|
||||
message: .expectedCustomValueTo(errorMessage, actual: "<\(stringify(actualValue))>")
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -19,73 +19,44 @@ internal func isCloseTo(_ actualValue: NMBDoubleConvertible?,
|
|||
/// point values which can have imprecise results when doing arithmetic on them.
|
||||
///
|
||||
/// @see equal
|
||||
public func beCloseTo(_ expectedValue: Double, within delta: Double = DefaultDelta) -> Predicate<Double> {
|
||||
public func beCloseTo<Value: NMBDoubleConvertible>(_ expectedValue: Value, within delta: Double = DefaultDelta) -> Predicate<Value> {
|
||||
return Predicate.define { actualExpression in
|
||||
return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is close to another. This is used for floating
|
||||
/// point values which can have imprecise results when doing arithmetic on them.
|
||||
///
|
||||
/// @see equal
|
||||
public func beCloseTo(_ expectedValue: NMBDoubleConvertible, within delta: Double = DefaultDelta) -> Predicate<NMBDoubleConvertible> {
|
||||
private func beCloseTo(_ expectedValue: NMBDoubleConvertible, within delta: Double = DefaultDelta) -> Predicate<NMBDoubleConvertible> {
|
||||
return Predicate.define { actualExpression in
|
||||
return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
var _expected: NSNumber
|
||||
var _delta: CDouble
|
||||
// swiftlint:enable identifier_name
|
||||
init(expected: NSNumber, within: CDouble) {
|
||||
public class NMBObjCBeCloseToPredicate: NMBPredicate {
|
||||
private let _expected: NSNumber
|
||||
|
||||
fileprivate init(expected: NSNumber, within: CDouble) {
|
||||
_expected = expected
|
||||
_delta = within
|
||||
}
|
||||
|
||||
@objc public func matches(_ actualExpression: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = beCloseTo(self._expected, within: self._delta)
|
||||
|
||||
do {
|
||||
return try matcher.matches(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
let predicate = beCloseTo(expected, within: within)
|
||||
let predicateBlock: PredicateBlock = { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBDoubleConvertible }
|
||||
return try predicate.satisfies(expr).toObjectiveC()
|
||||
}
|
||||
super.init(predicate: predicateBlock)
|
||||
}
|
||||
|
||||
@objc public func doesNotMatch(_ actualExpression: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = beCloseTo(self._expected, within: self._delta)
|
||||
|
||||
do {
|
||||
return try matcher.doesNotMatch(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
@objc public var within: (CDouble) -> NMBObjCBeCloseToPredicate {
|
||||
let expected = _expected
|
||||
return { delta in
|
||||
return NMBObjCBeCloseToPredicate(expected: expected, within: delta)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var within: (CDouble) -> NMBObjCBeCloseToMatcher {
|
||||
return ({ delta in
|
||||
return NMBObjCBeCloseToMatcher(expected: self._expected, within: delta)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beCloseToMatcher(_ expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToMatcher {
|
||||
return NMBObjCBeCloseToMatcher(expected: expected, within: within)
|
||||
extension NMBPredicate {
|
||||
@objc public class func beCloseToMatcher(_ expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToPredicate {
|
||||
return NMBObjCBeCloseToPredicate(expected: expected, within: within)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -113,23 +84,27 @@ public func beCloseTo(_ expectedValues: [Double], within delta: Double = Default
|
|||
|
||||
infix operator ≈ : ComparisonPrecedence
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
extension Expectation where T == [Double] {
|
||||
// swiftlint:disable:next identifier_name
|
||||
public static func ≈(lhs: Expectation, rhs: [Double]) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<NMBDoubleConvertible>, rhs: NMBDoubleConvertible) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
extension Expectation where T == NMBDoubleConvertible {
|
||||
// swiftlint:disable:next identifier_name
|
||||
public static func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<NMBDoubleConvertible>, rhs: (expected: NMBDoubleConvertible, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
// swiftlint:disable:next identifier_name
|
||||
public static func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
|
||||
public func == (lhs: Expectation<NMBDoubleConvertible>, rhs: (expected: NMBDoubleConvertible, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
public static func == (lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
}
|
||||
|
||||
// make this higher precedence than exponents so the Doubles either end aren't pulled in
|
||||
|
|
|
@ -4,11 +4,9 @@ import Foundation
|
|||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty<S: Sequence>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualSeq = try actualExpression.evaluate()
|
||||
if actualSeq == nil {
|
||||
return .fail
|
||||
}
|
||||
var generator = actualSeq!.makeIterator()
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
var generator = actual.makeIterator()
|
||||
return PredicateStatus(bool: generator.next() == nil)
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +15,16 @@ public func beEmpty<S: Sequence>() -> Predicate<S> {
|
|||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty<S: SetAlgebra>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else {
|
||||
return .fail
|
||||
}
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty<S: Sequence & SetAlgebra>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.isEmpty)
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +33,8 @@ public func beEmpty<S: SetAlgebra>() -> Predicate<S> {
|
|||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> Predicate<String> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualString = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0)
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +42,8 @@ public func beEmpty() -> Predicate<String> {
|
|||
/// means the are no items in that collection. For NSString instances, it is an empty string.
|
||||
public func beEmpty() -> Predicate<NSString> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualString = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actualString == nil || actualString!.length == 0)
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.length == 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,42 +53,42 @@ public func beEmpty() -> Predicate<NSString> {
|
|||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> Predicate<NSDictionary> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualDictionary = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.count == 0)
|
||||
}
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.count == 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> Predicate<NSArray> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualArray = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actualArray == nil || actualArray!.count == 0)
|
||||
}
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.count == 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> Predicate<NMBCollection> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actual == nil || actual!.count == 0)
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
return PredicateStatus(bool: actual.count == 0)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beEmptyMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
|
||||
if let value = actualValue as? NMBCollection {
|
||||
let expr = Expression(expression: ({ value as NMBCollection }), location: location)
|
||||
let expr = Expression(expression: ({ value }), location: location)
|
||||
return try beEmpty().satisfies(expr).toObjectiveC()
|
||||
} else if let value = actualValue as? NSString {
|
||||
let expr = Expression(expression: ({ value as String }), location: location)
|
||||
let expr = Expression(expression: ({ value }), location: location)
|
||||
return try beEmpty().satisfies(expr).toObjectiveC()
|
||||
} else if let actualValue = actualValue {
|
||||
// swiftlint:disable:next line_length
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than the expected value.
|
||||
public func beGreaterThan<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
let errorMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(errorMessage) { actualExpression in
|
||||
if let actual = try actualExpression.evaluate(), let expected = expectedValue {
|
||||
return PredicateStatus(bool: actual > expected)
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: actual > expected)
|
||||
}
|
||||
}
|
||||
|
||||
public func ><T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import enum Foundation.ComparisonResult
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than the expected value.
|
||||
public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate<NMBComparable> {
|
||||
let errorMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
|
@ -22,17 +26,12 @@ public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate<NMBCompa
|
|||
}
|
||||
}
|
||||
|
||||
public func ><T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
public func > (lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try beGreaterThan(expected).satisfies(expr).toObjectiveC()
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
let message = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let actual = actualValue, let expected = expectedValue {
|
||||
return PredicateStatus(bool: actual >= expected)
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: actual >= expected)
|
||||
}
|
||||
}
|
||||
|
||||
public func >=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import enum Foundation.ComparisonResult
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
|
@ -24,17 +27,12 @@ public func beGreaterThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Pre
|
|||
}
|
||||
}
|
||||
|
||||
public func >=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
public func >=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
|
||||
|
|
|
@ -1,36 +1,28 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is the same instance
|
||||
/// as the expected instance.
|
||||
public func beIdenticalTo(_ expected: Any?) -> Predicate<Any> {
|
||||
return Predicate.define { actualExpression in
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
let actual = try actualExpression.evaluate() as? AnyObject
|
||||
#else
|
||||
let actual = try actualExpression.evaluate() as AnyObject?
|
||||
#endif
|
||||
let actual = try actualExpression.evaluate() as AnyObject?
|
||||
|
||||
let bool: Bool
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
bool = actual === (expected as? AnyObject) && actual !== nil
|
||||
#else
|
||||
bool = actual === (expected as AnyObject?) && actual !== nil
|
||||
#endif
|
||||
let bool = actual === (expected as AnyObject?) && actual !== nil
|
||||
return PredicateResult(
|
||||
bool: bool,
|
||||
message: .expectedCustomValueTo(
|
||||
"be identical to \(identityAsString(expected))",
|
||||
"\(identityAsString(actual))"
|
||||
actual: "\(identityAsString(actual))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func === (lhs: Expectation<Any>, rhs: Any?) {
|
||||
lhs.to(beIdenticalTo(rhs))
|
||||
}
|
||||
public func !== (lhs: Expectation<Any>, rhs: Any?) {
|
||||
lhs.toNot(beIdenticalTo(rhs))
|
||||
extension Expectation where T == Any {
|
||||
public static func === (lhs: Expectation, rhs: Any?) {
|
||||
lhs.to(beIdenticalTo(rhs))
|
||||
}
|
||||
|
||||
public static func !== (lhs: Expectation, rhs: Any?) {
|
||||
lhs.toNot(beIdenticalTo(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is the same instance
|
||||
|
@ -42,8 +34,10 @@ public func be(_ expected: Any?) -> Predicate<Any> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBMatcher {
|
||||
import class Foundation.NSObject
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let aExpr = actualExpression.cast { $0 as Any? }
|
||||
return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC()
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
let message = "be less than <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
if let actual = try actualExpression.evaluate(), let expected = expectedValue {
|
||||
return PredicateStatus(bool: actual < expected)
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: actual < expected)
|
||||
}
|
||||
}
|
||||
|
||||
public func <<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import enum Foundation.ComparisonResult
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate<NMBComparable> {
|
||||
let message = "be less than <\(stringify(expectedValue))>"
|
||||
|
@ -21,17 +25,12 @@ public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate<NMBComparab
|
|||
}
|
||||
}
|
||||
|
||||
public func <<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
public func < (lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try beLessThan(expected).satisfies(expr).toObjectiveC()
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate(), let expected = expectedValue {
|
||||
return PredicateStatus(bool: actual <= expected)
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: actual <= expected)
|
||||
}
|
||||
}
|
||||
|
||||
public func <=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import enum Foundation.ComparisonResult
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
|
@ -21,17 +25,12 @@ public func beLessThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Predic
|
|||
}
|
||||
}
|
||||
|
||||
public func <=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
public func <=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
|
||||
|
|
|
@ -119,29 +119,29 @@ public func beFalsy<T: ExpressibleByBooleanLiteral & Equatable>() -> Predicate<T
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beTruthyMatcher() -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beTruthyMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try beTruthy().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beFalsyMatcher() -> NMBMatcher {
|
||||
@objc public class func beFalsyMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try beFalsy().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beTrueMatcher() -> NMBMatcher {
|
||||
@objc public class func beTrueMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try beTrue().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beFalseMatcher() -> NMBMatcher {
|
||||
@objc public class func beFalseMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { value -> Bool? in
|
||||
guard let value = value else { return nil }
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is nil.
|
||||
public func beNil<T>() -> Predicate<T> {
|
||||
return Predicate.simpleNilable("be nil") { actualExpression in
|
||||
|
@ -9,8 +7,10 @@ public func beNil<T>() -> Predicate<T> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beNilMatcher() -> NMBMatcher {
|
||||
import Foundation
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func beNilMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beNil().satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is Void.
|
||||
public func beVoid() -> Predicate<()> {
|
||||
return Predicate.simpleNilable("be void") { actualExpression in
|
||||
|
|
|
@ -2,14 +2,12 @@ import Foundation
|
|||
|
||||
/// A Nimble matcher that succeeds when the actual sequence's first element
|
||||
/// is equal to the expected value.
|
||||
public func beginWith<S: Sequence, T: Equatable>(_ startingElement: T) -> Predicate<S>
|
||||
where S.Iterator.Element == T {
|
||||
public func beginWith<S: Sequence>(_ startingElement: S.Element) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("begin with <\(startingElement)>") { actualExpression in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
return PredicateStatus(bool: actualGenerator.next() == startingElement)
|
||||
}
|
||||
return .fail
|
||||
guard let actualValue = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
return PredicateStatus(bool: actualGenerator.next() == startingElement)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,16 +32,15 @@ public func beginWith(_ startingElement: Any) -> Predicate<NMBOrderedCollection>
|
|||
/// where the expected substring's location is zero.
|
||||
public func beginWith(_ startingSubstring: String) -> Predicate<String> {
|
||||
return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
return PredicateStatus(bool: actual.hasPrefix(startingSubstring))
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: actual.hasPrefix(startingSubstring))
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func beginWithMatcher(_ expected: Any) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
if actual is String {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/// A Nimble matcher that succeeds when the exepected sequence is a prefix of the actual sequence.
|
||||
///
|
||||
/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2854218-starts
|
||||
public func beginWith<Seq1: Sequence, Seq2: Sequence>(prefix expectedPrefix: Seq2?)
|
||||
-> Predicate<Seq1> where Seq1.Element: Equatable, Seq1.Element == Seq2.Element {
|
||||
return Predicate.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in
|
||||
let actualPrefix = try actualExpression.evaluate()
|
||||
switch (expectedPrefix, actualPrefix) {
|
||||
case (nil, _?):
|
||||
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
|
||||
case (nil, nil), (_, nil):
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
case (let expected?, let actual?):
|
||||
let matches = actual.starts(with: expected)
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the expected sequence is the prefix of the actual sequence, using the given predicate as the equivalence test.
|
||||
///
|
||||
/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2996828-starts
|
||||
public func beginWith<Seq1: Sequence, Seq2: Sequence>(
|
||||
prefix expectedPrefix: Seq2?,
|
||||
by areEquivalent: @escaping (Seq1.Element, Seq2.Element) -> Bool
|
||||
) -> Predicate<Seq1> {
|
||||
return Predicate.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in
|
||||
let actualPrefix = try actualExpression.evaluate()
|
||||
switch (expectedPrefix, actualPrefix) {
|
||||
case (nil, _?):
|
||||
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
|
||||
case (nil, nil), (_, nil):
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
case (let expected?, let actual?):
|
||||
let matches = actual.starts(with: expected, by: areEquivalent)
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +1,56 @@
|
|||
#if canImport(Foundation)
|
||||
import Foundation
|
||||
#endif
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected values.
|
||||
public func contain<S: Sequence, T: Equatable>(_ items: T...) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
public func contain<S: Sequence>(_ items: S.Element...) -> Predicate<S> where S.Element: Equatable {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected values.
|
||||
public func contain<S: Sequence, T: Equatable>(_ items: [T]) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
public func contain<S: Sequence>(_ items: [S.Element]) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return .fail
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: SetAlgebra, T: Equatable>(_ items: T...) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return contain(items)
|
||||
public func contain<S: SetAlgebra>(_ items: S.Element...) -> Predicate<S> where S.Element: Equatable {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: SetAlgebra, T: Equatable>(_ items: [T]) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return .fail
|
||||
public func contain<S: SetAlgebra>(_ items: [S.Element]) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: Sequence & SetAlgebra>(_ items: S.Element...) -> Predicate<S> where S.Element: Equatable {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: Sequence & SetAlgebra>(_ items: [S.Element]) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
|
||||
|
@ -47,17 +60,17 @@ public func contain(_ substrings: String...) -> Predicate<String> {
|
|||
|
||||
public func contain(_ substrings: [String]) -> Predicate<String> {
|
||||
return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = substrings.allSatisfy {
|
||||
let range = actual.range(of: $0)
|
||||
return range != nil && !range!.isEmpty
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = substrings.allSatisfy {
|
||||
let range = actual.range(of: $0)
|
||||
return range != nil && !range!.isEmpty
|
||||
}
|
||||
return .fail
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Foundation)
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
|
||||
public func contain(_ substrings: NSString...) -> Predicate<NSString> {
|
||||
return contain(substrings)
|
||||
|
@ -65,13 +78,13 @@ public func contain(_ substrings: NSString...) -> Predicate<NSString> {
|
|||
|
||||
public func contain(_ substrings: [NSString]) -> Predicate<NSString> {
|
||||
return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = substrings.allSatisfy { actual.range(of: $0.description).length != 0 }
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return .fail
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = substrings.allSatisfy { actual.range(of: $0.description).length != 0 }
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection contains the expected object.
|
||||
public func contain(_ items: Any?...) -> Predicate<NMBContainer> {
|
||||
|
@ -81,6 +94,7 @@ public func contain(_ items: Any?...) -> Predicate<NMBContainer> {
|
|||
public func contain(_ items: [Any?]) -> Predicate<NMBContainer> {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
let matches = items.allSatisfy { item in
|
||||
return item.map { actual.contains($0) } ?? false
|
||||
}
|
||||
|
@ -89,8 +103,8 @@ public func contain(_ items: [Any?]) -> Predicate<NMBContainer> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func containMatcher(_ expected: [NSObject]) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func containMatcher(_ expected: [NSObject]) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Foundation
|
||||
|
||||
public func containElementSatisfying<S: Sequence, T>(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate<S> where S.Iterator.Element == T {
|
||||
|
||||
public func containElementSatisfying<S: Sequence>(
|
||||
_ predicate: @escaping ((S.Element) -> Bool), _ predicateDescription: String = ""
|
||||
) -> Predicate<S> {
|
||||
return Predicate.define { actualExpression in
|
||||
let message: ExpectationMessage
|
||||
if predicateDescription == "" {
|
||||
|
@ -25,34 +24,38 @@ public func containElementSatisfying<S: Sequence, T>(_ predicate: @escaping ((T)
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let value = try actualExpression.evaluate()
|
||||
guard let enumeration = value as? NSFastEnumeration else {
|
||||
let message = ExpectationMessage.fail(
|
||||
"containElementSatisfying must be provided an NSFastEnumeration object"
|
||||
)
|
||||
return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
|
||||
}
|
||||
import class Foundation.NSObject
|
||||
import struct Foundation.NSFastEnumerationIterator
|
||||
import protocol Foundation.NSFastEnumeration
|
||||
|
||||
let message = ExpectationMessage
|
||||
.expectedTo("find object in collection that satisfies predicate")
|
||||
.toObjectiveC()
|
||||
|
||||
var iterator = NSFastEnumerationIterator(enumeration)
|
||||
while let item = iterator.next() {
|
||||
guard let object = item as? NSObject else {
|
||||
continue
|
||||
}
|
||||
|
||||
if predicate(object) {
|
||||
return NMBPredicateResult(status: .matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
return NMBPredicateResult(status: .doesNotMatch, message: message)
|
||||
extension NMBPredicate {
|
||||
@objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let value = try actualExpression.evaluate()
|
||||
guard let enumeration = value as? NSFastEnumeration else {
|
||||
let message = ExpectationMessage.fail(
|
||||
"containElementSatisfying must be provided an NSFastEnumeration object"
|
||||
)
|
||||
return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
|
||||
}
|
||||
|
||||
let message = ExpectationMessage
|
||||
.expectedTo("find object in collection that satisfies predicate")
|
||||
.toObjectiveC()
|
||||
|
||||
var iterator = NSFastEnumerationIterator(enumeration)
|
||||
while let item = iterator.next() {
|
||||
guard let object = item as? NSObject else {
|
||||
continue
|
||||
}
|
||||
|
||||
if predicate(object) {
|
||||
return NMBPredicateResult(status: .matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
return NMBPredicateResult(status: .doesNotMatch, message: message)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/// A Nimble matcher that succeeds when the actual sequence contain the same elements in the same order to the exepected sequence.
|
||||
public func elementsEqual<S: Sequence>(_ expectedValue: S?) -> Predicate<S> where S.Element: Equatable {
|
||||
// A matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal
|
||||
/// A Nimble matcher that succeeds when the actual sequence and the exepected sequence contain the same elements in
|
||||
/// the same order.
|
||||
///
|
||||
/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2854213-elementsequal
|
||||
public func elementsEqual<Seq1: Sequence, Seq2: Sequence>(
|
||||
_ expectedValue: Seq2?
|
||||
) -> Predicate<Seq1> where Seq1.Element: Equatable, Seq1.Element == Seq2.Element {
|
||||
return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
switch (expectedValue, actualValue) {
|
||||
|
@ -14,3 +18,25 @@ public func elementsEqual<S: Sequence>(_ expectedValue: S?) -> Predicate<S> wher
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence and the exepected sequence contain equivalent elements in
|
||||
/// the same order, using the given predicate as the equivalence test.
|
||||
///
|
||||
/// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal
|
||||
public func elementsEqual<Seq1: Sequence, Seq2: Sequence>(
|
||||
_ expectedValue: Seq2?,
|
||||
by areEquivalent: @escaping (Seq1.Element, Seq2.Element) -> Bool
|
||||
) -> Predicate<Seq1> {
|
||||
return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
switch (expectedValue, actualValue) {
|
||||
case (nil, _?):
|
||||
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
|
||||
case (nil, nil), (_, nil):
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
case (let expected?, let actual?):
|
||||
let matches = actual.elementsEqual(expected, by: areEquivalent)
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,21 +2,19 @@ import Foundation
|
|||
|
||||
/// A Nimble matcher that succeeds when the actual sequence's last element
|
||||
/// is equal to the expected value.
|
||||
public func endWith<S: Sequence, T: Equatable>(_ endingElement: T) -> Predicate<S>
|
||||
where S.Iterator.Element == T {
|
||||
public func endWith<S: Sequence>(_ endingElement: S.Element) -> Predicate<S> where S.Element: Equatable {
|
||||
return Predicate.simple("end with <\(endingElement)>") { actualExpression in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
var lastItem: T?
|
||||
var item: T?
|
||||
repeat {
|
||||
lastItem = item
|
||||
item = actualGenerator.next()
|
||||
} while(item != nil)
|
||||
guard let actualValue = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: lastItem == endingElement)
|
||||
}
|
||||
return .fail
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
var lastItem: S.Element?
|
||||
var item: S.Element?
|
||||
repeat {
|
||||
lastItem = item
|
||||
item = actualGenerator.next()
|
||||
} while(item != nil)
|
||||
|
||||
return PredicateStatus(bool: lastItem == endingElement)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +23,7 @@ public func endWith<S: Sequence, T: Equatable>(_ endingElement: T) -> Predicate<
|
|||
public func endWith(_ endingElement: Any) -> Predicate<NMBOrderedCollection> {
|
||||
return Predicate.simple("end with <\(endingElement)>") { actualExpression in
|
||||
guard let collection = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
guard collection.count > 0 else { return PredicateStatus(bool: false) }
|
||||
#if os(Linux)
|
||||
guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else {
|
||||
|
@ -43,16 +42,15 @@ public func endWith(_ endingElement: Any) -> Predicate<NMBOrderedCollection> {
|
|||
/// expected substring's length.
|
||||
public func endWith(_ endingSubstring: String) -> Predicate<String> {
|
||||
return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in
|
||||
if let collection = try actualExpression.evaluate() {
|
||||
return PredicateStatus(bool: collection.hasSuffix(endingSubstring))
|
||||
}
|
||||
return .fail
|
||||
guard let collection = try actualExpression.evaluate() else { return .fail }
|
||||
|
||||
return PredicateStatus(bool: collection.hasSuffix(endingSubstring))
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func endWithMatcher(_ expected: Any) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func endWithMatcher(_ expected: Any) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
if actual is String {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
|
||||
/// Values can support equal by supporting the Equatable protocol.
|
||||
///
|
||||
|
@ -71,7 +69,7 @@ private func equal<T>(_ expectedValue: Set<T>?, stringify: @escaping (Set<T>?) -
|
|||
|
||||
errorMessage = .expectedCustomValueTo(
|
||||
"equal <\(stringify(expectedValue))>",
|
||||
"<\(stringify(actualValue))>"
|
||||
actual: "<\(stringify(actualValue))>"
|
||||
)
|
||||
|
||||
if expectedValue == actualValue {
|
||||
|
@ -138,8 +136,10 @@ public func !=<T, C: Equatable>(lhs: Expectation<[T: C]>, rhs: [T: C]?) {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher {
|
||||
import class Foundation.NSObject
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func equalMatcher(_ expected: NSObject) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try equal(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
// The `haveCount` matchers do not print the full string representation of the collection value,
|
||||
// instead they only print the type name and the expected count. This makes it easier to understand
|
||||
// the reason for failed expectations. See: https://github.com/Quick/Nimble/issues/308.
|
||||
|
@ -13,7 +11,7 @@ public func haveCount<T: Collection>(_ expectedValue: Int) -> Predicate<T> {
|
|||
let message = ExpectationMessage
|
||||
.expectedCustomValueTo(
|
||||
"have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
|
||||
"\(actualValue.count)"
|
||||
actual: "\(actualValue.count)"
|
||||
)
|
||||
.appended(details: "Actual Value: \(stringify(actualValue))")
|
||||
|
||||
|
@ -33,7 +31,7 @@ public func haveCount(_ expectedValue: Int) -> Predicate<NMBCollection> {
|
|||
let message = ExpectationMessage
|
||||
.expectedCustomValueTo(
|
||||
"have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
|
||||
"\(actualValue.count)"
|
||||
actual: "\(actualValue.count)"
|
||||
)
|
||||
.appended(details: "Actual Value: \(stringify(actualValue))")
|
||||
|
||||
|
@ -46,8 +44,10 @@ public func haveCount(_ expectedValue: Int) -> Predicate<NMBCollection> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBMatcher {
|
||||
import Foundation
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
|
@ -60,7 +60,7 @@ extension NMBObjCMatcher {
|
|||
if let actualValue = actualValue {
|
||||
message = ExpectationMessage.expectedCustomValueTo(
|
||||
"get type of NSArray, NSSet, NSDictionary, or NSHashTable",
|
||||
"\(String(describing: type(of: actualValue)))"
|
||||
actual: "\(String(describing: type(of: actualValue)))"
|
||||
)
|
||||
} else {
|
||||
message = ExpectationMessage
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string satisfies the regular expression
|
||||
/// described by the expected string.
|
||||
public func match(_ expectedValue: String?) -> Predicate<String> {
|
||||
return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
if let regexp = expectedValue {
|
||||
let bool = actual.range(of: regexp, options: .regularExpression) != nil
|
||||
return PredicateStatus(bool: bool)
|
||||
}
|
||||
}
|
||||
guard let actual = try actualExpression.evaluate(), let regexp = expectedValue else { return .fail }
|
||||
|
||||
return .fail
|
||||
let bool = actual.range(of: regexp, options: .regularExpression) != nil
|
||||
return PredicateStatus(bool: bool)
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSString
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher {
|
||||
extension NMBPredicate {
|
||||
@objc public class func matchMatcher(_ expected: NSString) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = actualExpression.cast { $0 as? String }
|
||||
return try match(expected.description).satisfies(actual).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression evaluates to an
|
||||
/// error from the specified case.
|
||||
///
|
||||
|
@ -9,9 +7,7 @@ public func matchError<T: Error>(_ error: T) -> Predicate<Error> {
|
|||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
error: error
|
||||
|
@ -22,7 +18,7 @@ public func matchError<T: Error>(_ error: T) -> Predicate<Error> {
|
|||
matches = true
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,9 +31,7 @@ public func matchError<T: Error & Equatable>(_ error: T) -> Predicate<Error> {
|
|||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
error: error
|
||||
|
@ -48,7 +42,7 @@ public func matchError<T: Error & Equatable>(_ error: T) -> Predicate<Error> {
|
|||
matches = true
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,9 +52,7 @@ public func matchError<T: Error>(_ errorType: T.Type) -> Predicate<Error> {
|
|||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
errorType: errorType
|
||||
|
@ -71,6 +63,6 @@ public func matchError<T: Error>(_ errorType: T.Type) -> Predicate<Error> {
|
|||
matches = true
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/// Use the Matcher protocol instead of this type to accept custom matchers as
|
||||
/// input parameters.
|
||||
/// @see allPass for an example that uses accepts other matchers as input.
|
||||
@available(*, deprecated, message: "Use to Predicate instead")
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public struct MatcherFunc<T>: Matcher {
|
||||
public let matcher: (Expression<T>, FailureMessage) throws -> Bool
|
||||
|
||||
|
@ -28,6 +28,7 @@ public struct MatcherFunc<T>: Matcher {
|
|||
/// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one.
|
||||
/// Note: You should definitely spend the time to convert to the new api as soon as possible
|
||||
/// since this struct type is deprecated.
|
||||
@available(*, deprecated, message: "Use Predicate directly instead")
|
||||
public var predicate: Predicate<T> {
|
||||
return Predicate.fromDeprecatedMatcher(self)
|
||||
}
|
||||
|
@ -44,7 +45,7 @@ public struct MatcherFunc<T>: Matcher {
|
|||
/// Use the Matcher protocol instead of this type to accept custom matchers as
|
||||
/// input parameters.
|
||||
/// @see allPass for an example that uses accepts other matchers as input.
|
||||
@available(*, deprecated, message: "Use to Predicate instead")
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public struct NonNilMatcherFunc<T>: Matcher {
|
||||
public let matcher: (Expression<T>, FailureMessage) throws -> Bool
|
||||
|
||||
|
@ -79,6 +80,7 @@ public struct NonNilMatcherFunc<T>: Matcher {
|
|||
/// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one.
|
||||
/// Note: You should definitely spend the time to convert to the new api as soon as possible
|
||||
/// since this struct type is deprecated.
|
||||
@available(*, deprecated, message: "Use Predicate directly instead")
|
||||
public var predicate: Predicate<T> {
|
||||
return Predicate.fromDeprecatedMatcher(self)
|
||||
}
|
||||
|
|
|
@ -12,19 +12,20 @@ public protocol Matcher {
|
|||
func doesNotMatch(_ actualExpression: Expression<ValueType>, failureMessage: FailureMessage) throws -> Bool
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
extension Matcher {
|
||||
var predicate: Predicate<ValueType> {
|
||||
return Predicate.fromDeprecatedMatcher(self)
|
||||
}
|
||||
|
||||
var toClosure: (Expression<ValueType>, FailureMessage, Bool) throws -> Bool {
|
||||
return ({ expr, msg, expectedResult in
|
||||
return { expr, msg, expectedResult in
|
||||
if expectedResult {
|
||||
return try self.matches(expr, failureMessage: msg)
|
||||
} else {
|
||||
return try self.doesNotMatch(expr, failureMessage: msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,20 +129,14 @@ extension NSDate: TestOutputStringConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
/// Protocol for types to support beLessThan(), beLessThanOrEqualTo(),
|
||||
/// beGreaterThan(), beGreaterThanOrEqualTo(), and equal() matchers.
|
||||
///
|
||||
/// Types that conform to Swift's Comparable protocol will work implicitly too
|
||||
#if canImport(Darwin)
|
||||
@objc public protocol NMBComparable {
|
||||
func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult
|
||||
}
|
||||
#else
|
||||
// This should become obsolete once Corelibs Foundation adds Comparable conformance to NSNumber
|
||||
public protocol NMBComparable {
|
||||
func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult
|
||||
}
|
||||
#endif
|
||||
|
||||
extension NSNumber: NMBComparable {
|
||||
public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult {
|
||||
|
@ -155,3 +150,4 @@ extension NSString: NMBComparable {
|
|||
return compare(otherObject as! String)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,48 +1,115 @@
|
|||
#if canImport(Foundation)
|
||||
import Foundation
|
||||
|
||||
internal class NotificationCollector {
|
||||
private(set) var observedNotifications: [Notification]
|
||||
private let notificationCenter: NotificationCenter
|
||||
#if canImport(Darwin)
|
||||
private var token: AnyObject?
|
||||
#else
|
||||
private var token: NSObjectProtocol?
|
||||
#endif
|
||||
private let names: Set<Notification.Name>
|
||||
private var tokens: [NSObjectProtocol]
|
||||
|
||||
required init(notificationCenter: NotificationCenter) {
|
||||
required init(notificationCenter: NotificationCenter, names: Set<Notification.Name> = []) {
|
||||
self.notificationCenter = notificationCenter
|
||||
self.observedNotifications = []
|
||||
self.names = names
|
||||
self.tokens = []
|
||||
}
|
||||
|
||||
func startObserving() {
|
||||
// swiftlint:disable:next line_length
|
||||
self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] notification in
|
||||
// linux-swift gets confused by .append(n)
|
||||
self?.observedNotifications.append(notification)
|
||||
func addObserver(forName name: Notification.Name?) -> NSObjectProtocol {
|
||||
return notificationCenter.addObserver(forName: name, object: nil, queue: nil) { [weak self] notification in
|
||||
// linux-swift gets confused by .append(n)
|
||||
self?.observedNotifications.append(notification)
|
||||
}
|
||||
}
|
||||
|
||||
if names.isEmpty {
|
||||
tokens.append(addObserver(forName: nil))
|
||||
} else {
|
||||
names.forEach { name in
|
||||
tokens.append(addObserver(forName: name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if canImport(Darwin)
|
||||
if let token = self.token {
|
||||
self.notificationCenter.removeObserver(token)
|
||||
}
|
||||
#else
|
||||
if let token = self.token as? AnyObject {
|
||||
self.notificationCenter.removeObserver(token)
|
||||
}
|
||||
#endif
|
||||
tokens.forEach { token in
|
||||
notificationCenter.removeObserver(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let mainThread = pthread_self()
|
||||
|
||||
private func _postNotifications<Out>(
|
||||
_ predicate: Predicate<[Notification]>,
|
||||
from center: NotificationCenter,
|
||||
names: Set<Notification.Name> = []
|
||||
) -> Predicate<Out> {
|
||||
_ = mainThread // Force lazy-loading of this value
|
||||
let collector = NotificationCollector(notificationCenter: center, names: names)
|
||||
collector.startObserving()
|
||||
var once: Bool = false
|
||||
|
||||
return Predicate { actualExpression in
|
||||
let collectorNotificationsExpression = Expression(
|
||||
memoizedExpression: { _ in
|
||||
return collector.observedNotifications
|
||||
},
|
||||
location: actualExpression.location,
|
||||
withoutCaching: true
|
||||
)
|
||||
|
||||
assert(pthread_equal(mainThread, pthread_self()) != 0, "Only expecting closure to be evaluated on main thread.")
|
||||
if !once {
|
||||
once = true
|
||||
_ = try actualExpression.evaluate()
|
||||
}
|
||||
|
||||
let actualValue: String
|
||||
if collector.observedNotifications.isEmpty {
|
||||
actualValue = "no notifications"
|
||||
} else {
|
||||
actualValue = "<\(stringify(collector.observedNotifications))>"
|
||||
}
|
||||
|
||||
var result = try predicate.satisfies(collectorNotificationsExpression)
|
||||
result.message = result.message.replacedExpectation { message in
|
||||
return .expectedCustomValueTo(message.expectedMessage, actual: actualValue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
public func postNotifications<Out>(
|
||||
_ predicate: Predicate<[Notification]>,
|
||||
from center: NotificationCenter = .default
|
||||
) -> Predicate<Out> {
|
||||
_postNotifications(predicate, from: center)
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "postNotifications(_:from:)")
|
||||
public func postNotifications<Out>(
|
||||
_ predicate: Predicate<[Notification]>,
|
||||
fromNotificationCenter center: NotificationCenter
|
||||
) -> Predicate<Out> {
|
||||
postNotifications(predicate, from: center)
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
public func postDistributedNotifications<Out>(
|
||||
_ predicate: Predicate<[Notification]>,
|
||||
from center: DistributedNotificationCenter = .default(),
|
||||
names: Set<Notification.Name>
|
||||
) -> Predicate<Out> {
|
||||
_postNotifications(predicate, from: center, names: names)
|
||||
}
|
||||
#endif
|
||||
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func postNotifications<T>(
|
||||
_ notificationsMatcher: T,
|
||||
fromNotificationCenter center: NotificationCenter = .default)
|
||||
-> Predicate<Any>
|
||||
where T: Matcher, T.ValueType == [Notification]
|
||||
{
|
||||
from center: NotificationCenter = .default
|
||||
) -> Predicate<Any> where T: Matcher, T.ValueType == [Notification] {
|
||||
_ = mainThread // Force lazy-loading of this value
|
||||
let collector = NotificationCollector(notificationCenter: center)
|
||||
collector.startObserving()
|
||||
|
@ -69,3 +136,12 @@ public func postNotifications<T>(
|
|||
return PredicateResult(bool: match, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "postNotifications(_:from:)")
|
||||
public func postNotifications<T>(
|
||||
_ notificationsMatcher: T,
|
||||
fromNotificationCenter center: NotificationCenter
|
||||
) -> Predicate<Any> where T: Matcher, T.ValueType == [Notification] {
|
||||
return postNotifications(notificationsMatcher, from: center)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// New Matcher API
|
||||
//
|
||||
import Foundation
|
||||
|
||||
/// A Predicate is part of the new matcher API that provides assertions to expectations.
|
||||
///
|
||||
|
@ -45,17 +44,17 @@ extension Predicate {
|
|||
|
||||
/// Defines a predicate with a default message that can be returned in the closure
|
||||
/// Also ensures the predicate's actual value cannot pass with `nil` given.
|
||||
public static func define(_ msg: String, matcher: @escaping (Expression<T>, ExpectationMessage) throws -> PredicateResult) -> Predicate<T> {
|
||||
public static func define(_ message: String = "match", matcher: @escaping (Expression<T>, ExpectationMessage) throws -> PredicateResult) -> Predicate<T> {
|
||||
return Predicate<T> { actual in
|
||||
return try matcher(actual, .expectedActualValueTo(msg))
|
||||
return try matcher(actual, .expectedActualValueTo(message))
|
||||
}.requireNonNil
|
||||
}
|
||||
|
||||
/// Defines a predicate with a default message that can be returned in the closure
|
||||
/// Unlike `define`, this allows nil values to succeed if the given closure chooses to.
|
||||
public static func defineNilable(_ msg: String, matcher: @escaping (Expression<T>, ExpectationMessage) throws -> PredicateResult) -> Predicate<T> {
|
||||
public static func defineNilable(_ message: String = "match", matcher: @escaping (Expression<T>, ExpectationMessage) throws -> PredicateResult) -> Predicate<T> {
|
||||
return Predicate<T> { actual in
|
||||
return try matcher(actual, .expectedActualValueTo(msg))
|
||||
return try matcher(actual, .expectedActualValueTo(message))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,9 +64,9 @@ extension Predicate {
|
|||
/// error message.
|
||||
///
|
||||
/// Also ensures the predicate's actual value cannot pass with `nil` given.
|
||||
public static func simple(_ msg: String, matcher: @escaping (Expression<T>) throws -> PredicateStatus) -> Predicate<T> {
|
||||
public static func simple(_ message: String = "match", matcher: @escaping (Expression<T>) throws -> PredicateStatus) -> Predicate<T> {
|
||||
return Predicate<T> { actual in
|
||||
return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg))
|
||||
return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(message))
|
||||
}.requireNonNil
|
||||
}
|
||||
|
||||
|
@ -75,9 +74,9 @@ extension Predicate {
|
|||
/// error message.
|
||||
///
|
||||
/// Unlike `simple`, this allows nil values to succeed if the given closure chooses to.
|
||||
public static func simpleNilable(_ msg: String, matcher: @escaping (Expression<T>) throws -> PredicateStatus) -> Predicate<T> {
|
||||
public static func simpleNilable(_ message: String = "match", matcher: @escaping (Expression<T>) throws -> PredicateStatus) -> Predicate<T> {
|
||||
return Predicate<T> { actual in
|
||||
return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg))
|
||||
return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(message))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +165,24 @@ public enum PredicateStatus {
|
|||
}
|
||||
}
|
||||
|
||||
extension Predicate {
|
||||
/// Compatibility layer for old Matcher API, deprecated.
|
||||
/// Emulates the MatcherFunc API
|
||||
internal static func _fromDeprecatedClosure(_ matcher: @escaping (Expression<T>, FailureMessage) throws -> Bool) -> Predicate {
|
||||
// swiftlint:disable:previous identifier_name
|
||||
return Predicate { actual in
|
||||
let failureMessage = FailureMessage()
|
||||
let result = try matcher(actual, failureMessage)
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: result),
|
||||
message: failureMessage.toExpectationMessage()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Backwards compatibility until Old Matcher API removal
|
||||
@available(*, deprecated, message: "Use Predicate directly instead")
|
||||
extension Predicate: Matcher {
|
||||
/// Compatibility layer for old Matcher API, deprecated
|
||||
public static func fromDeprecatedFullClosure(_ matcher: @escaping (Expression<T>, FailureMessage, Bool) throws -> Bool) -> Predicate {
|
||||
|
@ -183,15 +199,7 @@ extension Predicate: Matcher {
|
|||
/// Compatibility layer for old Matcher API, deprecated.
|
||||
/// Emulates the MatcherFunc API
|
||||
public static func fromDeprecatedClosure(_ matcher: @escaping (Expression<T>, FailureMessage) throws -> Bool) -> Predicate {
|
||||
return Predicate { actual in
|
||||
let failureMessage = FailureMessage()
|
||||
let result = try matcher(actual, failureMessage)
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: result),
|
||||
message: failureMessage.toExpectationMessage()
|
||||
)
|
||||
}
|
||||
|
||||
return _fromDeprecatedClosure(matcher)
|
||||
}
|
||||
|
||||
/// Compatibility layer for old Matcher API, deprecated.
|
||||
|
@ -243,6 +251,8 @@ extension Predicate {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
import class Foundation.NSObject
|
||||
|
||||
public typealias PredicateBlock = (_ actualExpression: Expression<NSObject>) throws -> NMBPredicateResult
|
||||
|
||||
public class NMBPredicate: NSObject {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Foundation
|
||||
|
||||
// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager
|
||||
// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
import class Foundation.NSObject
|
||||
import class Foundation.NSDictionary
|
||||
import class Foundation.NSException
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an
|
||||
/// exception with the specified name, reason, and/or userInfo.
|
||||
|
@ -12,78 +13,97 @@ import Foundation
|
|||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func raiseException(
|
||||
named: String? = nil,
|
||||
public func raiseException<Out>(
|
||||
named: NSExceptionName? = nil,
|
||||
reason: String? = nil,
|
||||
userInfo: NSDictionary? = nil,
|
||||
closure: ((NSException) -> Void)? = nil) -> Predicate<Any> {
|
||||
return Predicate { actualExpression in
|
||||
var exception: NSException?
|
||||
let capture = NMBExceptionCapture(handler: ({ e in
|
||||
exception = e
|
||||
}), finally: nil)
|
||||
|
||||
do {
|
||||
try capture.tryBlockThrows {
|
||||
_ = try actualExpression.evaluate()
|
||||
}
|
||||
} catch {
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>"))
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForException(
|
||||
failureMessage,
|
||||
exception: exception,
|
||||
named: named,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
|
||||
let matches = exceptionMatchesNonNilFieldsOrClosure(
|
||||
exception,
|
||||
named: named,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
closure: ((NSException) -> Void)? = nil
|
||||
) -> Predicate<Out> {
|
||||
return raiseException(named: named?.rawValue, reason: reason, userInfo: userInfo, closure: closure)
|
||||
}
|
||||
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
internal func setFailureMessageForException(
|
||||
_ failureMessage: FailureMessage,
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an
|
||||
/// exception with the specified name, reason, and/or userInfo.
|
||||
///
|
||||
/// Alternatively, you can pass a closure to do any arbitrary custom matching
|
||||
/// to the raised exception. The closure only gets called when an exception
|
||||
/// is raised.
|
||||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func raiseException<Out>(
|
||||
named: String?,
|
||||
reason: String? = nil,
|
||||
userInfo: NSDictionary? = nil,
|
||||
closure: ((NSException) -> Void)? = nil
|
||||
) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var exception: NSException?
|
||||
let capture = NMBExceptionCapture(handler: ({ e in
|
||||
exception = e
|
||||
}), finally: nil)
|
||||
|
||||
do {
|
||||
try capture.tryBlockThrows {
|
||||
_ = try actualExpression.evaluate()
|
||||
}
|
||||
} catch {
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>"))
|
||||
}
|
||||
|
||||
let message = messageForException(
|
||||
exception: exception,
|
||||
named: named,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
|
||||
let matches = exceptionMatchesNonNilFieldsOrClosure(
|
||||
exception,
|
||||
named: named,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
internal func messageForException(
|
||||
exception: NSException?,
|
||||
named: String?,
|
||||
reason: String?,
|
||||
userInfo: NSDictionary?,
|
||||
closure: ((NSException) -> Void)?) {
|
||||
failureMessage.postfixMessage = "raise exception"
|
||||
closure: ((NSException) -> Void)?
|
||||
) -> ExpectationMessage {
|
||||
var rawMessage: String = "raise exception"
|
||||
|
||||
if let named = named {
|
||||
failureMessage.postfixMessage += " with name <\(named)>"
|
||||
}
|
||||
if let reason = reason {
|
||||
failureMessage.postfixMessage += " with reason <\(reason)>"
|
||||
}
|
||||
if let userInfo = userInfo {
|
||||
failureMessage.postfixMessage += " with userInfo <\(userInfo)>"
|
||||
}
|
||||
if closure != nil {
|
||||
failureMessage.postfixMessage += " that satisfies block"
|
||||
}
|
||||
if named == nil && reason == nil && userInfo == nil && closure == nil {
|
||||
failureMessage.postfixMessage = "raise any exception"
|
||||
}
|
||||
if let named = named {
|
||||
rawMessage += " with name <\(named)>"
|
||||
}
|
||||
if let reason = reason {
|
||||
rawMessage += " with reason <\(reason)>"
|
||||
}
|
||||
if let userInfo = userInfo {
|
||||
rawMessage += " with userInfo <\(userInfo)>"
|
||||
}
|
||||
if closure != nil {
|
||||
rawMessage += " that satisfies block"
|
||||
}
|
||||
if named == nil && reason == nil && userInfo == nil && closure == nil {
|
||||
rawMessage = "raise any exception"
|
||||
}
|
||||
|
||||
if let exception = exception {
|
||||
// swiftlint:disable:next line_length
|
||||
failureMessage.actualValue = "\(String(describing: type(of: exception))) { name=\(exception.name), reason='\(stringify(exception.reason))', userInfo=\(stringify(exception.userInfo)) }"
|
||||
} else {
|
||||
failureMessage.actualValue = "no exception"
|
||||
}
|
||||
let actual: String
|
||||
if let exception = exception {
|
||||
// swiftlint:disable:next line_length
|
||||
actual = "\(String(describing: type(of: exception))) { name=\(exception.name), reason='\(stringify(exception.reason))', userInfo=\(stringify(exception.userInfo)) }"
|
||||
} else {
|
||||
actual = "no exception"
|
||||
}
|
||||
|
||||
return .expectedCustomValueTo(rawMessage, actual: actual)
|
||||
}
|
||||
|
||||
internal func exceptionMatchesNonNilFieldsOrClosure(
|
||||
|
@ -121,90 +141,82 @@ internal func exceptionMatchesNonNilFieldsOrClosure(
|
|||
return matches
|
||||
}
|
||||
|
||||
public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
internal var _name: String?
|
||||
internal var _reason: String?
|
||||
internal var _userInfo: NSDictionary?
|
||||
internal var _block: ((NSException) -> Void)?
|
||||
// swiftlint:enable identifier_name
|
||||
public class NMBObjCRaiseExceptionPredicate: NMBPredicate {
|
||||
private let _name: String?
|
||||
private let _reason: String?
|
||||
private let _userInfo: NSDictionary?
|
||||
private let _block: ((NSException) -> Void)?
|
||||
|
||||
internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) {
|
||||
fileprivate init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) {
|
||||
_name = name
|
||||
_reason = reason
|
||||
_userInfo = userInfo
|
||||
_block = block
|
||||
|
||||
let predicate: Predicate<NSObject> = raiseException(
|
||||
named: name,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: block
|
||||
)
|
||||
let predicateBlock: PredicateBlock = { actualExpression in
|
||||
return try predicate.satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
super.init(predicate: predicateBlock)
|
||||
}
|
||||
|
||||
@objc public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let block: () -> Any? = ({ _ = actualBlock(); return nil })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
|
||||
do {
|
||||
return try raiseException(
|
||||
named: _name,
|
||||
reason: _reason,
|
||||
userInfo: _userInfo,
|
||||
closure: _block
|
||||
).matches(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
@objc public var named: (_ name: String) -> NMBObjCRaiseExceptionPredicate {
|
||||
let (reason, userInfo, block) = (_reason, _userInfo, _block)
|
||||
return { name in
|
||||
return NMBObjCRaiseExceptionPredicate(
|
||||
name: name,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
block: block
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
return !matches(actualBlock, failureMessage: failureMessage, location: location)
|
||||
}
|
||||
|
||||
@objc public var named: (_ name: String) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ name in
|
||||
return NMBObjCRaiseExceptionMatcher(
|
||||
@objc public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionPredicate {
|
||||
let (name, userInfo, block) = (_name, _userInfo, _block)
|
||||
return { reason in
|
||||
return NMBObjCRaiseExceptionPredicate(
|
||||
name: name,
|
||||
reason: self._reason,
|
||||
userInfo: self._userInfo,
|
||||
block: self._block
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@objc public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ reason in
|
||||
return NMBObjCRaiseExceptionMatcher(
|
||||
name: self._name,
|
||||
reason: reason,
|
||||
userInfo: self._userInfo,
|
||||
block: self._block
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@objc public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ userInfo in
|
||||
return NMBObjCRaiseExceptionMatcher(
|
||||
name: self._name,
|
||||
reason: self._reason,
|
||||
userInfo: userInfo,
|
||||
block: self._block
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@objc public var satisfyingBlock: (_ block: ((NSException) -> Void)?) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ block in
|
||||
return NMBObjCRaiseExceptionMatcher(
|
||||
name: self._name,
|
||||
reason: self._reason,
|
||||
userInfo: self._userInfo,
|
||||
block: block
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionPredicate {
|
||||
let (name, reason, block) = (_name, _reason, _block)
|
||||
return { userInfo in
|
||||
return NMBObjCRaiseExceptionPredicate(
|
||||
name: name,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
block: block
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var satisfyingBlock: (_ block: ((NSException) -> Void)?) -> NMBObjCRaiseExceptionPredicate {
|
||||
let (name, reason, userInfo) = (_name, _reason, _userInfo)
|
||||
return { block in
|
||||
return NMBObjCRaiseExceptionPredicate(
|
||||
name: name,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
block: block
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher {
|
||||
return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil)
|
||||
extension NMBPredicate {
|
||||
@objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionPredicate {
|
||||
return NMBObjCRaiseExceptionPredicate(name: nil, reason: nil, userInfo: nil, block: nil)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual value matches with all of the matchers
|
||||
/// provided in the variable list of matchers.
|
||||
public func satisfyAllOf<T>(_ predicates: Predicate<T>...) -> Predicate<T> {
|
||||
return satisfyAllOf(predicates)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value matches with all of the matchers
|
||||
/// provided in the variable list of matchers.
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func satisfyAllOf<T, U>(_ matchers: U...) -> Predicate<T>
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return satisfyAllOf(matchers.map { $0.predicate })
|
||||
|
@ -23,7 +28,7 @@ internal func satisfyAllOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
|
|||
if let actualValue = try actualExpression.evaluate() {
|
||||
msg = .expectedCustomValueTo(
|
||||
"match all of: " + postfixMessages.joined(separator: ", and "),
|
||||
"\(actualValue)"
|
||||
actual: "\(actualValue)"
|
||||
)
|
||||
} else {
|
||||
msg = .expectedActualValueTo(
|
||||
|
@ -40,7 +45,9 @@ public func && <T>(left: Predicate<T>, right: Predicate<T>) -> Predicate<T> {
|
|||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
import class Foundation.NSObject
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
if matchers.isEmpty {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual value matches with any of the matchers
|
||||
/// provided in the variable list of matchers.
|
||||
public func satisfyAnyOf<T>(_ predicates: Predicate<T>...) -> Predicate<T> {
|
||||
return satisfyAnyOf(predicates)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value matches with any of the matchers
|
||||
/// provided in the variable list of matchers.
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func satisfyAnyOf<T, U>(_ matchers: U...) -> Predicate<T>
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return satisfyAnyOf(matchers.map { $0.predicate })
|
||||
|
@ -23,7 +28,7 @@ internal func satisfyAnyOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
|
|||
if let actualValue = try actualExpression.evaluate() {
|
||||
msg = .expectedCustomValueTo(
|
||||
"match one of: " + postfixMessages.joined(separator: ", or "),
|
||||
"\(actualValue)"
|
||||
actual: "\(actualValue)"
|
||||
)
|
||||
} else {
|
||||
msg = .expectedActualValueTo(
|
||||
|
@ -39,16 +44,20 @@ public func || <T>(left: Predicate<T>, right: Predicate<T>) -> Predicate<T> {
|
|||
return satisfyAnyOf(left, right)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func || <T>(left: NonNilMatcherFunc<T>, right: NonNilMatcherFunc<T>) -> Predicate<T> {
|
||||
return satisfyAnyOf(left, right)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use Predicate instead")
|
||||
public func || <T>(left: MatcherFunc<T>, right: MatcherFunc<T>) -> Predicate<T> {
|
||||
return satisfyAnyOf(left, right)
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
import class Foundation.NSObject
|
||||
|
||||
extension NMBPredicate {
|
||||
@objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
if matchers.isEmpty {
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import Foundation
|
||||
#if canImport(CwlPreconditionTesting) && (os(macOS) || os(iOS))
|
||||
import CwlPreconditionTesting
|
||||
#elseif canImport(CwlPosixPreconditionTesting)
|
||||
import CwlPosixPreconditionTesting
|
||||
#endif
|
||||
|
||||
public func throwAssertion() -> Predicate<Void> {
|
||||
public func throwAssertion<Out>() -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
#if arch(x86_64) && canImport(Darwin) && !SWIFT_PACKAGE
|
||||
#if arch(x86_64) && canImport(Darwin)
|
||||
let message = ExpectationMessage.expectedTo("throw an assertion")
|
||||
|
||||
var actualError: Error?
|
||||
|
@ -24,7 +28,7 @@ public func throwAssertion() -> Predicate<Void> {
|
|||
}
|
||||
#endif
|
||||
do {
|
||||
try actualExpression.evaluate()
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
@ -38,10 +42,6 @@ public func throwAssertion() -> Predicate<Void> {
|
|||
} else {
|
||||
return PredicateResult(bool: caughtException != nil, message: message)
|
||||
}
|
||||
#elseif SWIFT_PACKAGE
|
||||
fatalError("The throwAssertion Nimble matcher does not currently support Swift CLI." +
|
||||
" You can silence this error by placing the test case inside an #if !SWIFT_PACKAGE" +
|
||||
" conditional statement")
|
||||
#else
|
||||
fatalError("The throwAssertion Nimble matcher can only run on x86_64 platforms with " +
|
||||
"Objective-C (e.g. macOS, iPhone 5s or later simulators). You can silence this error " +
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression throws an
|
||||
/// error of the specified type or from the specified case.
|
||||
///
|
||||
|
@ -11,7 +9,7 @@ import Foundation
|
|||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError() -> Predicate<Any> {
|
||||
public func throwError<Out>() -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -21,9 +19,15 @@ public func throwError() -> Predicate<Any> {
|
|||
}
|
||||
|
||||
if let actualError = actualError {
|
||||
return PredicateResult(bool: true, message: .expectedCustomValueTo("throw any error", "<\(actualError)>"))
|
||||
return PredicateResult(
|
||||
bool: true,
|
||||
message: .expectedCustomValueTo("throw any error", actual: "<\(actualError)>")
|
||||
)
|
||||
} else {
|
||||
return PredicateResult(bool: false, message: .expectedCustomValueTo("throw any error", "no error"))
|
||||
return PredicateResult(
|
||||
bool: false,
|
||||
message: .expectedCustomValueTo("throw any error", actual: "no error")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +43,7 @@ public func throwError() -> Predicate<Any> {
|
|||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate<Any> {
|
||||
public func throwError<T: Error, Out>(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -48,9 +52,7 @@ public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil)
|
|||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
actualError: actualError,
|
||||
error: error,
|
||||
errorType: nil,
|
||||
|
@ -72,7 +74,7 @@ public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil)
|
|||
}
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +89,7 @@ public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil)
|
|||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate<Any> {
|
||||
public func throwError<T: Error & Equatable, Out>(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -96,9 +98,7 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
|||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
actualError: actualError,
|
||||
error: error,
|
||||
errorType: nil,
|
||||
|
@ -120,7 +120,7 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
|||
}
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,9 +135,10 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
|||
///
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError<T: Error>(
|
||||
public func throwError<T: Error, Out>(
|
||||
errorType: T.Type,
|
||||
closure: ((T) -> Void)? = nil) -> Predicate<Any> {
|
||||
closure: ((T) -> Void)? = nil
|
||||
) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -146,9 +147,7 @@ public func throwError<T: Error>(
|
|||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
let message = messageForError(
|
||||
actualError: actualError,
|
||||
error: nil,
|
||||
errorType: errorType,
|
||||
|
@ -187,7 +186,7 @@ public func throwError<T: Error>(
|
|||
}
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +197,7 @@ public func throwError<T: Error>(
|
|||
/// values of the existential type `Error` in the closure.
|
||||
///
|
||||
/// The closure only gets called when an error was thrown.
|
||||
public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
||||
public func throwError<Out>(closure: @escaping ((Error) -> Void)) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -207,8 +206,7 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
|||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(failureMessage, actualError: actualError, closure: closure)
|
||||
let message = messageForError(actualError: actualError, closure: closure)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError {
|
||||
|
@ -223,7 +221,7 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
|||
}
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +232,7 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
|||
/// values of the existential type `Error` in the closure.
|
||||
///
|
||||
/// The closure only gets called when an error was thrown.
|
||||
public func throwError<T: Error>(closure: @escaping ((T) -> Void)) -> Predicate<Any> {
|
||||
public func throwError<T: Error, Out>(closure: @escaping ((T) -> Void)) -> Predicate<Out> {
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
|
@ -243,8 +241,7 @@ public func throwError<T: Error>(closure: @escaping ((T) -> Void)) -> Predicate<
|
|||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(failureMessage, actualError: actualError, closure: closure)
|
||||
let message = messageForError(actualError: actualError, closure: closure)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError as? T {
|
||||
|
@ -259,6 +256,6 @@ public func throwError<T: Error>(closure: @escaping ((T) -> Void)) -> Predicate<
|
|||
}
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
return PredicateResult(bool: matches, message: message)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,12 @@ public func succeed() -> Predicate<() -> ToSucceedResult> {
|
|||
case .succeeded:
|
||||
return PredicateResult(
|
||||
bool: true,
|
||||
message: .expectedCustomValueTo("succeed", "<succeeded>")
|
||||
message: .expectedCustomValueTo("succeed", actual: "<succeeded>")
|
||||
)
|
||||
case .failed(let reason):
|
||||
return PredicateResult(
|
||||
bool: false,
|
||||
message: .expectedCustomValueTo("succeed", "<failed> because <\(reason)>")
|
||||
message: .expectedCustomValueTo("succeed", actual: "<failed> because <\(reason)>")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
#import "NMBStringify.h"
|
||||
#import "DSL.h"
|
||||
|
||||
#if TARGET_OS_TV
|
||||
#import "CwlPreconditionTesting_POSIX.h"
|
||||
#else
|
||||
#import "CwlPreconditionTesting.h"
|
||||
#if TARGET_OS_OSX || TARGET_OS_IOS
|
||||
#import "CwlMachBadInstructionHandler.h"
|
||||
#import "CwlCatchException.h"
|
||||
#endif
|
||||
|
||||
FOUNDATION_EXPORT double NimbleVersionNumber;
|
||||
|
|
|
@ -2,10 +2,6 @@ import CoreFoundation
|
|||
import Dispatch
|
||||
import Foundation
|
||||
|
||||
#if canImport(CDispatch)
|
||||
import CDispatch
|
||||
#endif
|
||||
|
||||
private let timeoutLeeway = DispatchTimeInterval.milliseconds(1)
|
||||
private let pollLeeway = DispatchTimeInterval.milliseconds(1)
|
||||
|
||||
|
@ -32,11 +28,7 @@ internal class AssertionWaitLock: WaitLock {
|
|||
|
||||
func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) {
|
||||
let info = WaitingInfo(name: fnName, file: file, lineNumber: line)
|
||||
#if canImport(Darwin)
|
||||
let isMainThread = Thread.isMainThread
|
||||
#else
|
||||
let isMainThread = _CFIsMainThread()
|
||||
#endif
|
||||
let isMainThread = Thread.isMainThread
|
||||
nimblePrecondition(
|
||||
isMainThread,
|
||||
"InvalidNimbleAPIUsage",
|
||||
|
@ -102,7 +94,7 @@ internal enum AwaitResult<T> {
|
|||
|
||||
/// Holds the resulting value from an asynchronous expectation.
|
||||
/// This class is thread-safe at receiving an "response" to this promise.
|
||||
internal class AwaitPromise<T> {
|
||||
internal final class AwaitPromise<T> {
|
||||
private(set) internal var asyncResult: AwaitResult<T> = .incomplete
|
||||
private var signal: DispatchSemaphore
|
||||
|
||||
|
@ -156,7 +148,7 @@ internal class AwaitPromiseBuilder<T> {
|
|||
self.trigger = trigger
|
||||
}
|
||||
|
||||
func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self {
|
||||
func timeout(_ timeoutInterval: DispatchTimeInterval, forcefullyAbortTimeout: DispatchTimeInterval) -> Self {
|
||||
// = Discussion =
|
||||
//
|
||||
// There's a lot of technical decisions here that is useful to elaborate on. This is
|
||||
|
@ -261,11 +253,7 @@ internal class AwaitPromiseBuilder<T> {
|
|||
self.trigger.timeoutSource.resume()
|
||||
while self.promise.asyncResult.isIncomplete() {
|
||||
// Stopping the run loop does not work unless we run only 1 mode
|
||||
#if (swift(>=4.2) && canImport(Darwin)) || compiler(>=5.0)
|
||||
_ = RunLoop.current.run(mode: .default, before: .distantFuture)
|
||||
#else
|
||||
_ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture)
|
||||
#endif
|
||||
}
|
||||
|
||||
self.trigger.timeoutSource.cancel()
|
||||
|
@ -305,11 +293,19 @@ internal class Awaiter {
|
|||
let timeoutSource = createTimerSource(timeoutQueue)
|
||||
var completionCount = 0
|
||||
let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) {
|
||||
try closure {
|
||||
try closure { result in
|
||||
completionCount += 1
|
||||
if completionCount < 2 {
|
||||
if promise.resolveResult(.completed($0)) {
|
||||
CFRunLoopStop(CFRunLoopGetMain())
|
||||
func completeBlock() {
|
||||
if promise.resolveResult(.completed(result)) {
|
||||
CFRunLoopStop(CFRunLoopGetMain())
|
||||
}
|
||||
}
|
||||
|
||||
if Thread.isMainThread {
|
||||
completeBlock()
|
||||
} else {
|
||||
DispatchQueue.main.async { completeBlock() }
|
||||
}
|
||||
} else {
|
||||
fail("waitUntil(..) expects its completion closure to be only called once",
|
||||
|
@ -325,12 +321,12 @@ internal class Awaiter {
|
|||
trigger: trigger)
|
||||
}
|
||||
|
||||
func poll<T>(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder<T> {
|
||||
func poll<T>(_ pollInterval: DispatchTimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder<T> {
|
||||
let promise = AwaitPromise<T>()
|
||||
let timeoutSource = createTimerSource(timeoutQueue)
|
||||
let asyncSource = createTimerSource(asyncQueue)
|
||||
let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: asyncSource) {
|
||||
let interval = DispatchTimeInterval.nanoseconds(Int(pollInterval * TimeInterval(NSEC_PER_SEC)))
|
||||
let interval = pollInterval
|
||||
asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway)
|
||||
asyncSource.setEventHandler {
|
||||
do {
|
||||
|
@ -357,8 +353,8 @@ internal class Awaiter {
|
|||
}
|
||||
|
||||
internal func pollBlock(
|
||||
pollInterval: TimeInterval,
|
||||
timeoutInterval: TimeInterval,
|
||||
pollInterval: DispatchTimeInterval,
|
||||
timeoutInterval: DispatchTimeInterval,
|
||||
file: FileString,
|
||||
line: UInt,
|
||||
fnName: String = #function,
|
||||
|
@ -369,7 +365,7 @@ internal func pollBlock(
|
|||
return true
|
||||
}
|
||||
return nil
|
||||
}.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line)
|
||||
}.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval.divided).wait(fnName, file: file, line: line)
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import Dispatch
|
||||
|
||||
#if canImport(CDispatch)
|
||||
import CDispatch
|
||||
#endif
|
||||
|
||||
extension DispatchTimeInterval {
|
||||
// ** Note: We cannot simply divide the time interval because DispatchTimeInterval associated value type is Int
|
||||
var divided: DispatchTimeInterval {
|
||||
switch self {
|
||||
case let .seconds(val): return val < 2 ? .milliseconds(Int(Float(val)/2*1000)) : .seconds(val/2)
|
||||
case let .milliseconds(val): return .milliseconds(val/2)
|
||||
case let .microseconds(val): return .microseconds(val/2)
|
||||
case let .nanoseconds(val): return .nanoseconds(val/2)
|
||||
case .never: return .never
|
||||
@unknown default: fatalError("Unknown DispatchTimeInterval value")
|
||||
}
|
||||
}
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case let .seconds(val): return val == 1 ? "\(Float(val)) second" : "\(Float(val)) seconds"
|
||||
case let .milliseconds(val): return "\(Float(val)/1_000) seconds"
|
||||
case let .microseconds(val): return "\(Float(val)/1_000_000) seconds"
|
||||
case let .nanoseconds(val): return "\(Float(val)/1_000_000_000) seconds"
|
||||
default: fatalError("Unknown DispatchTimeInterval value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Foundation)
|
||||
import typealias Foundation.TimeInterval
|
||||
|
||||
extension TimeInterval {
|
||||
var dispatchInterval: DispatchTimeInterval {
|
||||
let microseconds = Int64(self * TimeInterval(USEC_PER_SEC))
|
||||
// perhaps use nanoseconds, though would more often be > Int.max
|
||||
return microseconds < Int.max ? .microseconds(Int(microseconds)) : .seconds(Int(self))
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,33 +1,34 @@
|
|||
import Foundation
|
||||
|
||||
// Generic
|
||||
|
||||
internal func setFailureMessageForError<T: Error>(
|
||||
_ failureMessage: FailureMessage,
|
||||
internal func messageForError<T: Error>(
|
||||
postfixMessageVerb: String = "throw",
|
||||
actualError: Error?,
|
||||
error: T? = nil,
|
||||
errorType: T.Type? = nil,
|
||||
closure: ((T) -> Void)? = nil) {
|
||||
failureMessage.postfixMessage = "\(postfixMessageVerb) error"
|
||||
closure: ((T) -> Void)? = nil
|
||||
) -> ExpectationMessage {
|
||||
var rawMessage = "\(postfixMessageVerb) error"
|
||||
|
||||
if let error = error {
|
||||
failureMessage.postfixMessage += " <\(error)>"
|
||||
rawMessage += " <\(error)>"
|
||||
} else if errorType != nil || closure != nil {
|
||||
failureMessage.postfixMessage += " from type <\(T.self)>"
|
||||
rawMessage += " from type <\(T.self)>"
|
||||
}
|
||||
if closure != nil {
|
||||
failureMessage.postfixMessage += " that satisfies block"
|
||||
rawMessage += " that satisfies block"
|
||||
}
|
||||
if error == nil && errorType == nil && closure == nil {
|
||||
failureMessage.postfixMessage = "\(postfixMessageVerb) any error"
|
||||
rawMessage = "\(postfixMessageVerb) any error"
|
||||
}
|
||||
|
||||
let actual: String
|
||||
if let actualError = actualError {
|
||||
failureMessage.actualValue = "<\(actualError)>"
|
||||
actual = "<\(actualError)>"
|
||||
} else {
|
||||
failureMessage.actualValue = "no error"
|
||||
actual = "no error"
|
||||
}
|
||||
|
||||
return .expectedCustomValueTo(rawMessage, actual: actual)
|
||||
}
|
||||
|
||||
internal func errorMatchesExpectedError<T: Error>(
|
||||
|
@ -39,21 +40,24 @@ internal func errorMatchesExpectedError<T: Error>(
|
|||
|
||||
// Non-generic
|
||||
|
||||
internal func setFailureMessageForError(
|
||||
_ failureMessage: FailureMessage,
|
||||
internal func messageForError(
|
||||
actualError: Error?,
|
||||
closure: ((Error) -> Void)?) {
|
||||
failureMessage.postfixMessage = "throw error"
|
||||
closure: ((Error) -> Void)?
|
||||
) -> ExpectationMessage {
|
||||
var rawMessage = "throw error"
|
||||
|
||||
if closure != nil {
|
||||
failureMessage.postfixMessage += " that satisfies block"
|
||||
rawMessage += " that satisfies block"
|
||||
} else {
|
||||
failureMessage.postfixMessage = "throw any error"
|
||||
rawMessage = "throw any error"
|
||||
}
|
||||
|
||||
let actual: String
|
||||
if let actualError = actualError {
|
||||
failureMessage.actualValue = "<\(actualError)>"
|
||||
actual = "<\(actualError)>"
|
||||
} else {
|
||||
failureMessage.actualValue = "no error"
|
||||
actual = "no error"
|
||||
}
|
||||
|
||||
return .expectedCustomValueTo(rawMessage, actual: actual)
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
#if !swift(>=4.2)
|
||||
extension Sequence {
|
||||
internal func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
|
||||
for item in self {
|
||||
if try !predicate(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,12 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
internal func identityAsString(_ value: Any?) -> String {
|
||||
let anyObject: AnyObject?
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
anyObject = value as? AnyObject
|
||||
#else
|
||||
anyObject = value as AnyObject?
|
||||
#endif
|
||||
let anyObject = value as AnyObject?
|
||||
if let value = anyObject {
|
||||
return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description
|
||||
} else {
|
||||
|
@ -45,32 +40,24 @@ extension Float: TestOutputStringConvertible {
|
|||
}
|
||||
|
||||
extension NSNumber: TestOutputStringConvertible {
|
||||
// This is using `NSString(format:)` instead of
|
||||
// `String(format:)` because the latter somehow breaks
|
||||
// the travis CI build on linux.
|
||||
public var testDescription: String {
|
||||
let description = self.description
|
||||
|
||||
if description.contains(".") {
|
||||
// Travis linux swiftpm build doesn't like casting String to NSString,
|
||||
// which is why this annoying nested initializer thing is here.
|
||||
// Maybe this will change in a future snapshot.
|
||||
let decimalPlaces = NSString(string: NSString(string: description)
|
||||
.components(separatedBy: ".")[1])
|
||||
|
||||
// SeeAlso: https://bugs.swift.org/browse/SR-1464
|
||||
switch decimalPlaces.length {
|
||||
let decimalPlaces = description.split(separator: ".")[1]
|
||||
switch decimalPlaces.count {
|
||||
case 1:
|
||||
return NSString(format: "%0.1f", self.doubleValue).description
|
||||
return String(format: "%0.1f", doubleValue)
|
||||
case 2:
|
||||
return NSString(format: "%0.2f", self.doubleValue).description
|
||||
return String(format: "%0.2f", doubleValue)
|
||||
case 3:
|
||||
return NSString(format: "%0.3f", self.doubleValue).description
|
||||
return String(format: "%0.3f", doubleValue)
|
||||
default:
|
||||
return NSString(format: "%0.4f", self.doubleValue).description
|
||||
return String(format: "%0.4f", doubleValue)
|
||||
}
|
||||
}
|
||||
return self.description
|
||||
|
||||
return description
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +72,7 @@ extension AnySequence: TestOutputStringConvertible {
|
|||
public var testDescription: String {
|
||||
let generator = self.makeIterator()
|
||||
var strings = [String]()
|
||||
var value: AnySequence.Iterator.Element?
|
||||
var value: AnySequence.Element?
|
||||
|
||||
repeat {
|
||||
value = generator.next()
|
||||
|
@ -121,13 +108,7 @@ extension String: TestOutputStringConvertible {
|
|||
|
||||
extension Data: TestOutputStringConvertible {
|
||||
public var testDescription: String {
|
||||
#if os(Linux)
|
||||
// swiftlint:disable:next todo
|
||||
// FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16)
|
||||
return "Data<length=\(count)>"
|
||||
#else
|
||||
return "Data<hash=\((self as NSData).hash),length=\(count)>"
|
||||
#endif
|
||||
return "Data<hash=\((self as NSData).hash),length=\(count)>"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class NMBExpectation;
|
||||
@class NMBObjCBeCloseToMatcher;
|
||||
@class NMBObjCRaiseExceptionMatcher;
|
||||
@protocol NMBMatcher;
|
||||
@class NMBPredicate;
|
||||
@class NMBObjCBeCloseToPredicate;
|
||||
@class NMBObjCRaiseExceptionPredicate;
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
@ -66,16 +66,16 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin
|
|||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_equal(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_equal(TYPE expectedValue) { \
|
||||
return NMB_equal((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> equal(TYPE expectedValue), NMB_equal(expectedValue));
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *equal(TYPE expectedValue), NMB_equal(expectedValue));
|
||||
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_equal(__nullable id expectedValue);
|
||||
NMBPredicate *NMB_equal(__nullable id expectedValue);
|
||||
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> equal(__nullable id expectedValue),
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *equal(__nullable id expectedValue),
|
||||
NMB_equal(expectedValue));
|
||||
|
||||
// overloaded dispatch for nils - expect(nil)
|
||||
|
@ -101,17 +101,17 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin
|
|||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_haveCount(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_haveCount(TYPE expectedValue) { \
|
||||
return NMB_haveCount((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> haveCount(TYPE expectedValue), \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *haveCount(TYPE expectedValue), \
|
||||
NMB_haveCount(expectedValue));
|
||||
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_haveCount(id expectedValue);
|
||||
NMBPredicate *NMB_haveCount(id expectedValue);
|
||||
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> haveCount(id expectedValue),
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *haveCount(id expectedValue),
|
||||
NMB_haveCount(expectedValue));
|
||||
|
||||
DEFINE_OVERLOAD(long, @(expectedValue))
|
||||
|
@ -127,14 +127,14 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin
|
|||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \
|
||||
NMBObjCBeCloseToPredicate *NMB_beCloseTo(TYPE expectedValue) { \
|
||||
return NMB_beCloseTo((NSNumber *)(EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToPredicate *beCloseTo(TYPE expectedValue), \
|
||||
NMB_beCloseTo(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue),
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToPredicate *NMB_beCloseTo(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToPredicate *beCloseTo(NSNumber *expectedValue),
|
||||
NMB_beCloseTo(expectedValue));
|
||||
|
||||
// it would be better to only overload float & double, but zero becomes ambigious
|
||||
|
@ -152,33 +152,33 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin
|
|||
|
||||
#undef DEFINE_OVERLOAD
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAnInstanceOf(Class expectedClass);
|
||||
NIMBLE_EXPORT_INLINE id<NMBMatcher> beAnInstanceOf(Class expectedClass) {
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beAnInstanceOf(Class expectedClass);
|
||||
NIMBLE_EXPORT_INLINE NMBPredicate *beAnInstanceOf(Class expectedClass) {
|
||||
return NMB_beAnInstanceOf(expectedClass);
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAKindOf(Class expectedClass);
|
||||
NIMBLE_EXPORT_INLINE id<NMBMatcher> beAKindOf(Class expectedClass) {
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beAKindOf(Class expectedClass);
|
||||
NIMBLE_EXPORT_INLINE NMBPredicate *beAKindOf(Class expectedClass) {
|
||||
return NMB_beAKindOf(expectedClass);
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beginWith(id itemElementOrSubstring);
|
||||
NIMBLE_EXPORT_INLINE id<NMBMatcher> beginWith(id itemElementOrSubstring) {
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beginWith(id itemElementOrSubstring);
|
||||
NIMBLE_EXPORT_INLINE NMBPredicate *beginWith(id itemElementOrSubstring) {
|
||||
return NMB_beginWith(itemElementOrSubstring);
|
||||
}
|
||||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_beGreaterThan(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_beGreaterThan(TYPE expectedValue) { \
|
||||
return NMB_beGreaterThan((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue));
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_beGreaterThan(NSNumber *expectedValue);
|
||||
NMBPredicate *NMB_beGreaterThan(NSNumber *expectedValue);
|
||||
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> beGreaterThan(NSNumber *expectedValue) {
|
||||
NMBPredicate *beGreaterThan(NSNumber *expectedValue) {
|
||||
return NMB_beGreaterThan(expectedValue);
|
||||
}
|
||||
|
||||
|
@ -197,17 +197,17 @@ NIMBLE_EXPORT_INLINE id<NMBMatcher> beginWith(id itemElementOrSubstring) {
|
|||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \
|
||||
return NMB_beGreaterThanOrEqualTo((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> beGreaterThanOrEqualTo(TYPE expectedValue), \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *beGreaterThanOrEqualTo(TYPE expectedValue), \
|
||||
NMB_beGreaterThanOrEqualTo(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue);
|
||||
NMBPredicate *NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue);
|
||||
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> beGreaterThanOrEqualTo(NSNumber *expectedValue) {
|
||||
NMBPredicate *beGreaterThanOrEqualTo(NSNumber *expectedValue) {
|
||||
return NMB_beGreaterThanOrEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
|
@ -225,28 +225,28 @@ NIMBLE_EXPORT_INLINE id<NMBMatcher> beginWith(id itemElementOrSubstring) {
|
|||
|
||||
#undef DEFINE_OVERLOAD
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beIdenticalTo(id expectedInstance);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beIdenticalTo(id expectedInstance),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beIdenticalTo(id expectedInstance);
|
||||
NIMBLE_SHORT(NMBPredicate *beIdenticalTo(id expectedInstance),
|
||||
NMB_beIdenticalTo(expectedInstance));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_be(id expectedInstance);
|
||||
NIMBLE_SHORT(id<NMBMatcher> be(id expectedInstance),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_be(id expectedInstance);
|
||||
NIMBLE_SHORT(NMBPredicate *be(id expectedInstance),
|
||||
NMB_be(expectedInstance));
|
||||
|
||||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_beLessThan(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_beLessThan(TYPE expectedValue) { \
|
||||
return NMB_beLessThan((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> beLessThan(TYPE expectedValue), \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *beLessThan(TYPE expectedValue), \
|
||||
NMB_beLessThan(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_beLessThan(NSNumber *expectedValue);
|
||||
NMBPredicate *NMB_beLessThan(NSNumber *expectedValue);
|
||||
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> beLessThan(NSNumber *expectedValue) {
|
||||
NMBPredicate *beLessThan(NSNumber *expectedValue) {
|
||||
return NMB_beLessThan(expectedValue);
|
||||
}
|
||||
|
||||
|
@ -266,18 +266,18 @@ NIMBLE_SHORT(id<NMBMatcher> be(id expectedInstance),
|
|||
|
||||
#define DEFINE_OVERLOAD(TYPE, EXPR) \
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \
|
||||
id<NMBMatcher> NMB_beLessThanOrEqualTo(TYPE expectedValue) { \
|
||||
NMBPredicate *NMB_beLessThanOrEqualTo(TYPE expectedValue) { \
|
||||
return NMB_beLessThanOrEqualTo((EXPR)); \
|
||||
} \
|
||||
NIMBLE_SHORT_OVERLOADED(id<NMBMatcher> beLessThanOrEqualTo(TYPE expectedValue), \
|
||||
NIMBLE_SHORT_OVERLOADED(NMBPredicate *beLessThanOrEqualTo(TYPE expectedValue), \
|
||||
NMB_beLessThanOrEqualTo(expectedValue));
|
||||
|
||||
|
||||
NIMBLE_EXPORT NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> NMB_beLessThanOrEqualTo(NSNumber *expectedValue);
|
||||
NMBPredicate *NMB_beLessThanOrEqualTo(NSNumber *expectedValue);
|
||||
|
||||
NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE
|
||||
id<NMBMatcher> beLessThanOrEqualTo(NSNumber *expectedValue) {
|
||||
NMBPredicate *beLessThanOrEqualTo(NSNumber *expectedValue) {
|
||||
return NMB_beLessThanOrEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
|
@ -294,63 +294,63 @@ NIMBLE_SHORT(id<NMBMatcher> be(id expectedInstance),
|
|||
|
||||
#undef DEFINE_OVERLOAD
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTruthy(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beTruthy(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beTruthy(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beTruthy(void),
|
||||
NMB_beTruthy());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalsy(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beFalsy(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beFalsy(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beFalsy(void),
|
||||
NMB_beFalsy());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTrue(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beTrue(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beTrue(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beTrue(void),
|
||||
NMB_beTrue());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalse(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beFalse(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beFalse(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beFalse(void),
|
||||
NMB_beFalse());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beNil(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beNil(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beNil(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beNil(void),
|
||||
NMB_beNil());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beEmpty(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beEmpty(void),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_beEmpty(void);
|
||||
NIMBLE_SHORT(NMBPredicate *beEmpty(void),
|
||||
NMB_beEmpty());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_containWithNilTermination(id itemOrSubstring, ...) NS_REQUIRES_NIL_TERMINATION;
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_containWithNilTermination(id itemOrSubstring, ...) NS_REQUIRES_NIL_TERMINATION;
|
||||
#define NMB_contain(...) NMB_containWithNilTermination(__VA_ARGS__, nil)
|
||||
#ifndef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define contain(...) NMB_contain(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_containElementSatisfying(BOOL(^predicate)(id));
|
||||
NIMBLE_SHORT(id<NMBMatcher> containElementSatisfying(BOOL(^predicate)(id)),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_containElementSatisfying(BOOL(^predicate)(id));
|
||||
NIMBLE_SHORT(NMBPredicate *containElementSatisfying(BOOL(^predicate)(id)),
|
||||
NMB_containElementSatisfying(predicate));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_endWith(id itemElementOrSubstring);
|
||||
NIMBLE_SHORT(id<NMBMatcher> endWith(id itemElementOrSubstring),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_endWith(id itemElementOrSubstring);
|
||||
NIMBLE_SHORT(NMBPredicate *endWith(id itemElementOrSubstring),
|
||||
NMB_endWith(itemElementOrSubstring));
|
||||
|
||||
NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void);
|
||||
NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void),
|
||||
NIMBLE_EXPORT NMBObjCRaiseExceptionPredicate *NMB_raiseException(void);
|
||||
NIMBLE_SHORT(NMBObjCRaiseExceptionPredicate *raiseException(void),
|
||||
NMB_raiseException());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_match(id expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> match(id expectedValue),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_match(id expectedValue);
|
||||
NIMBLE_SHORT(NMBPredicate *match(id expectedValue),
|
||||
NMB_match(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_allPass(id matcher);
|
||||
NIMBLE_SHORT(id<NMBMatcher> allPass(id matcher),
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_allPass(id matcher);
|
||||
NIMBLE_SHORT(NMBPredicate *allPass(id matcher),
|
||||
NMB_allPass(matcher));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAnyOfWithMatchers(id matchers);
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_satisfyAnyOfWithMatchers(id matchers);
|
||||
#define NMB_satisfyAnyOf(...) NMB_satisfyAnyOfWithMatchers(@[__VA_ARGS__])
|
||||
#ifndef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define satisfyAnyOf(...) NMB_satisfyAnyOf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAllOfWithMatchers(id matchers);
|
||||
NIMBLE_EXPORT NMBPredicate *NMB_satisfyAllOfWithMatchers(id matchers);
|
||||
#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__])
|
||||
#ifndef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue