diff --git a/Carthage/Checkouts/Commandant/.gitignore b/Carthage/Checkouts/Commandant/.gitignore new file mode 100644 index 0000000..415ffcb --- /dev/null +++ b/Carthage/Checkouts/Commandant/.gitignore @@ -0,0 +1,24 @@ +# Xcode +# +.DS_Store +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +*.xcscmblueprint + +Carthage/Build +Packages/ +.build/ diff --git a/Carthage/Checkouts/Commandant/.gitmodules b/Carthage/Checkouts/Commandant/.gitmodules new file mode 100644 index 0000000..8283dfc --- /dev/null +++ b/Carthage/Checkouts/Commandant/.gitmodules @@ -0,0 +1,12 @@ +[submodule "Carthage/Checkouts/Nimble"] + path = Carthage/Checkouts/Nimble + url = https://github.com/Quick/Nimble.git +[submodule "Carthage/Checkouts/Quick"] + path = Carthage/Checkouts/Quick + url = https://github.com/Quick/Quick.git +[submodule "Carthage/Checkouts/xcconfigs"] + path = Carthage/Checkouts/xcconfigs + url = https://github.com/jspahrsummers/xcconfigs.git +[submodule "Carthage/Checkouts/Result"] + path = Carthage/Checkouts/Result + url = https://github.com/antitypical/Result.git diff --git a/Carthage/Checkouts/Commandant/.swift-version b/Carthage/Checkouts/Commandant/.swift-version new file mode 100644 index 0000000..4d0dcda --- /dev/null +++ b/Carthage/Checkouts/Commandant/.swift-version @@ -0,0 +1 @@ +4.1.2 diff --git a/Carthage/Checkouts/Commandant/.travis.yml b/Carthage/Checkouts/Commandant/.travis.yml new file mode 100644 index 0000000..60bc687 --- /dev/null +++ b/Carthage/Checkouts/Commandant/.travis.yml @@ -0,0 +1,86 @@ +aliases: + - &xcode + script: set -o pipefail && xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" test | xcpretty + xcode_workspace: Commandant.xcworkspace + xcode_scheme: Commandant + os: osx + language: objective-c + - &cocoapods + script: + - rm .swift-version + - pod repo update master + - pod lib lint --verbose + os: osx + language: objective-c + env: JOB=CocoaPods + - &swiftpm + script: + - swift --version + - swift build + - swift test + git: + submodules: false + - &swiftpm_darwin + <<: *swiftpm + os: osx + language: objective-c + env: JOB=SPM + - &swiftpm_linux + <<: *swiftpm + sudo: required + dist: trusty + language: generic + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" + +branches: + only: + - master + +matrix: + include: + - <<: *xcode + osx_image: xcode9.2 + env: JOB=Xcode9.2 + - <<: *xcode + osx_image: xcode9.4 + env: JOB=Xcode9.4 + - <<: *cocoapods + osx_image: xcode9.4 + - <<: *swiftpm_darwin + osx_image: xcode9.2 + - <<: *swiftpm_darwin + osx_image: xcode9.4 + - <<: *swiftpm_linux + env: + - JOB=Linux + - SWIFT_VERSION=4.0.3 + - <<: *swiftpm_linux + env: + - JOB=Linux + - <<: *swiftpm_linux + env: + - JOB=Linux + - SWIFT_VERSION=4.2-DEVELOPMENT-SNAPSHOT-2018-07-05-a + +notifications: + email: false + slack: + secure: DBDJCDEfXVb4g1/vziIYpjwCE5dh75SwBGZAcqbk6wOl6KFS9lA+fk/PtAbuXAEkRNr5qv56aQ+NPRnjSdqmhKB9bwywxUI7LA1JlvxAk6HUya0XWLLH0dvkRJG1o6QWiOnZ79gjWvl/VuN/YH9X7SgwdTTA4xush8ogP+ku8YE= + +before_deploy: + - brew update + - brew outdated carthage || brew upgrade carthage + - carthage build --no-skip-current --platform mac + - carthage archive Commandant + +deploy: + provider: releases + api_key: + secure: C5x9Hj0fip8nfrke4AhGNDsmpQsjiB/Mbu6yKwW0MFn46cys64uPajKMDmwcK0512h4eW1HxkmKkaiqfv42gN3Qq+iDmmC7+DNSXgZQ/bj2h5O/t85L6Y+JQGhqbZ6XwAoEcyzFvmkbczR+Xtd0RwQR4WUhqIRElmlCfHe20ST8= + file: Commandant.framework.zip + skip_cleanup: true + on: + repo: Carthage/Commandant + tags: true + condition: $JOB = Xcode9.4 diff --git a/Carthage/Checkouts/Commandant/CONTRIBUTING.md b/Carthage/Checkouts/Commandant/CONTRIBUTING.md new file mode 100644 index 0000000..bc96c20 --- /dev/null +++ b/Carthage/Checkouts/Commandant/CONTRIBUTING.md @@ -0,0 +1,17 @@ +We love that you’re interested in contributing! + +Please file issues or submit pull requests for anything you’d like to see! We just have a couple of guidelines to make things easier for everyone involved. + +## Prefer pull requests + +If you know exactly how to implement the feature being suggested or fix the bug being reported, please open a pull request instead of an issue. Pull requests are easier than patches or inline code blocks for discussing and merging the changes. + +If you can’t make the change yourself, please open an issue after making sure that one isn’t already logged. + +## Code style + +If you’re interested in contributing code, please have a look at our [style guide](https://github.com/github/swift-style-guide), which we try to match fairly closely. + +If you have a case that is not covered in the style guide, simply do your best to match the style of the surrounding code. + +**Thanks for contributing! :boom::camel:** diff --git a/Carthage/Checkouts/Commandant/Cartfile b/Carthage/Checkouts/Commandant/Cartfile new file mode 100644 index 0000000..e9bc3ad --- /dev/null +++ b/Carthage/Checkouts/Commandant/Cartfile @@ -0,0 +1 @@ +github "antitypical/Result" ~> 4.0 diff --git a/Carthage/Checkouts/Commandant/Cartfile.private b/Carthage/Checkouts/Commandant/Cartfile.private new file mode 100644 index 0000000..bf6802d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Cartfile.private @@ -0,0 +1,3 @@ +github "jspahrsummers/xcconfigs" ~> 0.9 +github "Quick/Quick" ~> 1.3 +github "Quick/Nimble" ~> 7.1.2 diff --git a/Carthage/Checkouts/Commandant/Cartfile.resolved b/Carthage/Checkouts/Commandant/Cartfile.resolved new file mode 100644 index 0000000..26edfb2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Cartfile.resolved @@ -0,0 +1,4 @@ +github "Quick/Nimble" "v7.1.2" +github "Quick/Quick" "v1.3.0" +github "antitypical/Result" "4.0.0" +github "jspahrsummers/xcconfigs" "0.9" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Nimble/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.gitignore b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.gitignore new file mode 100644 index 0000000..6930efd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.gitignore @@ -0,0 +1,29 @@ +.DS_Store +**/xcuserdata/* +**/*.xccheckout +**/*.xcscmblueprint +build/ +.idea +DerivedData/ +Nimble.framework.zip + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts +Carthage/Checkouts/**/*.* +Carthage/Checkouts/**/Cart* +Carthage/Checkouts/**/Tests +!Carthage/Checkouts/**/LICENSE.* +!Carthage/Checkouts/**/*.md +!Carthage/Checkouts/**/*.swift +!Carthage/Checkouts/**/*.h +!Carthage/Checkouts/**/*.m +!Carthage/Checkouts/**/*.c +Carthage/Build + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.hound.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swift-version b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swiftlint.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swiftlint.yml new file mode 100644 index 0000000..cb105e7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.swiftlint.yml @@ -0,0 +1,19 @@ +disabled_rules: + - todo + - variable_name + - force_try + - force_cast + +included: + - Sources + - Tests + +excluded: + - Carthage/Checkouts + +trailing_comma: + mandatory_comma: true + +line_length: + ignores_comments: true + ignores_function_declarations: true diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.travis.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.travis.yml new file mode 100644 index 0000000..20d7f7d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/.travis.yml @@ -0,0 +1,39 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + sudo: required + env: TYPE=podspec + - os: osx + env: TYPE=ios NIMBLE_RUNTIME_IOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=tvos NIMBLE_RUNTIME_TVOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=macos + - os: osx + env: TYPE=macos + osx_image: xcode9 + - os: osx + env: TYPE=swiftpm + - os: osx + env: TYPE=swiftpm + osx_image: xcode9 + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + - os: linux + dist: trusty + sudo: required + env: + - TYPE=swiftpm + - SWIFT_VERSION=4.0.2 + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" +install: + - if [[ "$TYPE" == "podspec" ]]; then sudo gem install bundler; bundle install; fi +script: + - ./test $TYPE diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/CONTRIBUTING.md @@ -0,0 +1,120 @@ + + + +- [Welcome to Nimble!](#welcome-to-nimble!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + + + +# Welcome to Nimble! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Nimble should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +**tl;dr:** If you've added a file to the project, make sure it's +included in both the OS X and iOS targets. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Nimble (eg - v2.0.0 or git sha `20a3f3b4e63cc8d97c92c4164bf36f2a2c9a6e1b`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- Use `Nimble.xcodeproj` to work on Nimble. + +## Running the Swift Package Manager tests + +1. Install `swiftenv` by running a line from the build script (`.travis.yml`): + + eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" + +2. Run `./test swiftpm` + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of Nimble + before submitting your pull request. You can run all the OS X & iOS unit + tests using `./test`. +- If you've added a file to the project, make sure it's included in both + the OS X and iOS targets. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +### Code of Conduct + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +### Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Nimble/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Update [Quick](https://github.com/Quick/Quick) + - Update Quick's submodule reference to the newly released Nimble version + - Update Nimble version in `README.md` and Documentation in [Quick](https://github.com/Quick/Quick) if it's not a patch version update. +- Announce! diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.private b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.private new file mode 100644 index 0000000..8e95dd6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.private @@ -0,0 +1 @@ +github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.resolved b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.resolved new file mode 100644 index 0000000..3984e09 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Cartfile.resolved @@ -0,0 +1,2 @@ +github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923" +github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt new file mode 100644 index 0000000..ca8f5b8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift new file mode 100644 index 0000000..c1e2ed8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift @@ -0,0 +1,9 @@ +import PackageDescription + +let package = Package( + name: "CwlCatchException", + targets: [ + Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]), + Target(name: "CwlCatchExceptionSupport") + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md new file mode 100644 index 0000000..0f97b03 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md @@ -0,0 +1,46 @@ +# 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. + +## 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), + +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" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..3e89e23 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,35 @@ +// +// CwlCatchException.swift +// CwlAssertionTesting +// +// 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 + +#if SWIFT_PACKAGE +import CwlCatchExceptionSupport +#endif + +private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { + return catchExceptionOfKind(type, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + return catchReturnTypeConverter(self, block: block) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m new file mode 100644 index 0000000..8cf414f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m @@ -0,0 +1,37 @@ +// +// CwlCatchException.m +// CwlAssertionTesting +// +// 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 "CwlCatchException.h" + +#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +__attribute__((visibility("hidden"))) +#endif +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h new file mode 100644 index 0000000..0c8dd87 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h @@ -0,0 +1,32 @@ +// +// CwlCatchException.h +// CwlCatchException +// +// 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 + +//! 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)); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt new file mode 100644 index 0000000..693a2fe --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift new file mode 100644 index 0000000..8792aac --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift @@ -0,0 +1,19 @@ +import PackageDescription + +let package = Package( + name: "CwlPreconditionTesting", + targets: [ + Target(name: "CwlPreconditionTesting", dependencies: [ + "CwlMachBadInstructionHandler" + ]), + Target(name: "CwlMachBadInstructionHandler") + ], + dependencies: [ + .Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])), + ], + exclude: [ + "Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a42a5b5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md @@ -0,0 +1,73 @@ +# CwlPreconditionTesting + +A Mach exception handler, written in Swift and Objective-C, that allows `EXC_BAD_INSTRUCTION` (as raised by Swift's `assertionFailure`/`preconditionFailure`/`fatalError`) to be caught and tested. + +NOTE: the iOS code runs in the simulator *only*. It is for logic testing and cannot be deployed to the device due to the Mach exception API being private on iOS. + +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) + +## 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), + +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/CwlPreconditionTesting.git", majorVersion: 1) + +### CocoaPods + +Add the following lines to your target in your "Podfile": + + pod 'CwlPreconditionTesting', :git => 'https://github.com/mattgallagher/CwlPreconditionTesting.git' + pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git' + +### Carthage + +Add the following line to your Cartfile: + + git "https://github.com/mattgallagher/CwlPreconditionTesting.git" "master" + +## 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) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m new file mode 100644 index 0000000..8183196 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m @@ -0,0 +1,50 @@ +// +// CwlMachBadExceptionHandler.m +// 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. +// + +#if defined(__x86_64__) + + #import "mach_excServer.h" + #import "CwlMachBadInstructionHandler.h" + + @protocol BadInstructionReply + +(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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h new file mode 100644 index 0000000..aef59c2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -0,0 +1,70 @@ +// +// CwlMachBadInstructionHandler.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 +#import + +NS_ASSUME_NONNULL_BEGIN + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; +} request_mach_exception_raise_t; + +// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; +} reply_mach_exception_raise_state_t; + +typedef struct +{ + mach_port_t exception_port; + exception_type_t exception; + mach_exception_data_type_t const * _Nullable code; + mach_msg_type_number_t codeCnt; + int32_t * _Nullable flavor; + natural_t const * _Nullable old_state; + mach_msg_type_number_t old_stateCnt; + thread_state_t _Nullable new_state; + mach_msg_type_number_t * _Nullable new_stateCnt; +} bad_instruction_exception_reply_t; + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c new file mode 100644 index 0000000..733c564 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Sun Jan 29 19:05:29 2017 + * with a MiG generated by bootstrap_cmds-96.20.2 + * OPTIONS: + */ + +#if defined(__x86_64__) + +/* Module mach_exc */ + +#define __MIG_check__Request__mach_exc_subsystem__ 1 + +#include "mach_excServer.h" + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + + typedef __Request__mach_exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise") + __BeforeRcvRpc(2405, "mach_exception_raise") + +#if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state") + __BeforeRcvRpc(2406, "mach_exception_raise_state") + +#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") + +#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity") +} + + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = { + mach_exc_server_routine, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + OutHeadP->msgh_reserved = 0; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h new file mode 100644 index 0000000..52e53ae --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h @@ -0,0 +1,321 @@ +#ifndef _mach_exc_server_ +#define _mach_exc_server_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +/* BEGIN MIG_STRNCPY_ZEROFILL CODE */ + +#if defined(__has_include) +#if __has_include() +#ifndef USING_MIG_STRNCPY_ZEROFILL +#define USING_MIG_STRNCPY_ZEROFILL +#endif +#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ +#endif /* __has_include() */ +#endif /* __has_include */ + +/* END MIG_STRNCPY_ZEROFILL CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigServerHeader +__BeforeMigServerHeader +#endif /* __BeforeMigServerHeader */ + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +mig_routine_t mach_exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +extern const struct catch_mach_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem; + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + + +/* union of all requests */ + +#ifndef __RequestUnion__catch_mach_exc_subsystem__defined +#define __RequestUnion__catch_mach_exc_subsystem__defined +union __RequestUnion__catch_mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2405 },\ + { "mach_exception_raise_state", 2406 },\ + { "mach_exception_raise_state_identity", 2407 } +#endif + +#ifdef __AfterMigServerHeader +__AfterMigServerHeader +#endif /* __AfterMigServerHeader */ + +#endif /* _mach_exc_server_ */ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..91e5d4d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,89 @@ +// +// CwlBadInstructionException.swift +// 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 + +#if SWIFT_PACKAGE + import CwlMachBadInstructionHandler +#endif + +private func raiseBadInstructionException() { + BadInstructionException().raise() +} + +/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type. +@objc(BadInstructionException) +public class BadInstructionException: NSException { + static var name: String = "com.cocoawithlove.BadInstruction" + + init() { + super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// 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 = 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 = 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.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 + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..f96ec63 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,197 @@ +// +// CwlCatchBadInstruction.swift +// 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 + +#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) + } + } + + extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> 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(in block: (UnsafeMutablePointer) -> 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() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil + + static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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.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.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 + } + + /// 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) + } + } + + 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 + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift new file mode 100644 index 0000000..eb9bc19 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift @@ -0,0 +1,108 @@ +// +// 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.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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..8d99d5e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,55 @@ +// +// CwlDarwinDefinitions.swift +// 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 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.size / MemoryLayout.size) + + public let EXC_TYPES_COUNT = 14 + public struct execTypesCountTuple { + // 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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h new file mode 100644 index 0000000..f9dbedd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h @@ -0,0 +1,30 @@ +// +// 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 + +//! 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" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h new file mode 100644 index 0000000..3434a71 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h @@ -0,0 +1,27 @@ +// +// 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 + +//! Project version number for CwlUtils. +FOUNDATION_EXPORT double CwlPreconditionTesting_POSIXVersionNumber; + +//! Project version string for CwlUtils. +FOUNDATION_EXPORT const unsigned char CwlAssertingTesting_POSIXVersionString[]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Dockerfile.test b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Dockerfile.test new file mode 100644 index 0000000..a995ae2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Dockerfile.test @@ -0,0 +1,3 @@ +FROM swift:latest +COPY . . +CMD ./test swiftpm diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile new file mode 100644 index 0000000..eca9219 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.5.0' diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile.lock b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile.lock new file mode 100644 index 0000000..36a0839 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Gemfile.lock @@ -0,0 +1,76 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + atomos (0.1.2) + claide (1.0.2) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + minitest (5.11.3) + molinillo (0.6.5) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + ruby-macho (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.5.0) + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/LICENSE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.podspec b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.podspec new file mode 100644 index 0000000..6aaf25e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.podspec @@ -0,0 +1,52 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "7.1.2" + 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. + DESC + 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.osx.deployment_target = "10.10" + s.tvos.deployment_target = "9.0" + s.source = { :git => "https://github.com/Quick/Nimble.git", + :tag => "v#{s.version}" } + + s.source_files = [ + "Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlCatchException/Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/**/*.{swift,h,m,c}", + ] + + s.osx.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.ios.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.tvos.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", + ] + + s.exclude_files = "Sources/Nimble/Adapters/NonObjectiveC/*.swift" + s.weak_framework = "XCTest" + s.requires_arc = true + s.compiler_flags = '-DPRODUCT_NAME=Nimble/Nimble' + s.pod_target_xcconfig = { + 'APPLICATION_EXTENSION_API_ONLY' => 'YES', + 'ENABLE_BITCODE' => 'NO', + 'OTHER_LDFLAGS' => '-weak-lswiftXCTest', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..eba6712 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2353 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + A8F2B2541E79A4AB005BDD17 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + A8F2B2581E79A4B0005BDD17 /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F1A74291940169200FFFC47 /* Nimble.framework */; }; + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 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 */; }; + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A56671A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; }; + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; }; + 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 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; }; + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; }; + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; }; + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + 1F5DF1AA1BDCA10200C3A531 /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F925EAD195C0D6300ED456B /* Nimble.framework */; }; + 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F925EE2195C0DFD00ED456B /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFD195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 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 */; }; + 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 */; }; + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C41E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.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 */; }; + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + CD79C9A51D2CC848004B6F9A /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + CD79C9A71D2CC848004B6F9A /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + CD79C9AF1D2CC848004B6F9A /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; }; + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 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 */; }; + 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 */; }; + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; }; + 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, ); }; }; + CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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 */; }; + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F5DF1541BDCA0CE00C3A531; + remoteInfo = "Nimble-tvOS"; + }; + 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = ""; }; + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTests.swift; sourceTree = ""; }; + 1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = ""; }; + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSL.h; sourceTree = ""; }; + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSL.m; sourceTree = ""; }; + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBExceptionCapture.h; sourceTree = ""; }; + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBExceptionCapture.m; sourceTree = ""; }; + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBStringify.h; sourceTree = ""; }; + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBStringify.m; sourceTree = ""; }; + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBExpectation.swift; sourceTree = ""; }; + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBObjCMatcher.swift; sourceTree = ""; }; + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionCapture.swift; sourceTree = ""; }; + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMatcherWrapper.swift; sourceTree = ""; }; + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherFunc.swift; sourceTree = ""; }; + 1F1A74291940169200FFFC47 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A742D1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1A742E1940169200FFFC47 /* Nimble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nimble.h; sourceTree = ""; }; + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A743A1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAKindOfTest.swift; sourceTree = ""; }; + 1F2752D119445B8400052A26 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = README.md; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.markdown; }; + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmptyTest.swift; sourceTree = ""; }; + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAsyncTest.m; sourceTree = ""; }; + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NimbleSpecHelper.h; sourceTree = ""; }; + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeAnInstanceOfTest.m; sourceTree = ""; }; + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeKindOfTest.m; sourceTree = ""; }; + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeCloseToTest.m; sourceTree = ""; }; + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeginWithTest.m; sourceTree = ""; }; + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanTest.m; sourceTree = ""; }; + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeIdenticalToTest.m; sourceTree = ""; }; + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanTest.m; sourceTree = ""; }; + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTruthyTest.m; sourceTree = ""; }; + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalsyTest.m; sourceTree = ""; }; + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTrueTest.m; sourceTree = ""; }; + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalseTest.m; sourceTree = ""; }; + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeNilTest.m; sourceTree = ""; }; + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainTest.m; sourceTree = ""; }; + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEndWithTest.m; sourceTree = ""; }; + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEqualTest.m; sourceTree = ""; }; + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCMatchTest.m; sourceTree = ""; }; + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCRaiseExceptionTest.m; sourceTree = ""; }; + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertionTest.swift; sourceTree = ""; }; + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSyncTest.m; sourceTree = ""; }; + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoidTest.swift; sourceTree = ""; }; + 1F91DD301C74BF61002C309F /* BeVoid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoid.swift; sourceTree = ""; }; + 1F925EAD195C0D6300ED456B /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousTest.swift; sourceTree = ""; }; + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOfTest.swift; sourceTree = ""; }; + 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaisesExceptionTest.swift; sourceTree = ""; }; + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLogicalTest.swift; sourceTree = ""; }; + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseToTest.swift; sourceTree = ""; }; + 1F925EF8195C175000ED456B /* BeNilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeNilTest.swift; sourceTree = ""; }; + 1F925EFB195C186800ED456B /* BeginWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeginWithTest.swift; sourceTree = ""; }; + 1F925EFE195C187600ED456B /* EndWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWithTest.swift; sourceTree = ""; }; + 1F925F01195C189500ED456B /* ContainTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainTest.swift; sourceTree = ""; }; + 1F925F04195C18B700ED456B /* EqualTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EqualTest.swift; sourceTree = ""; }; + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanTest.swift; sourceTree = ""; }; + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanTest.swift; sourceTree = ""; }; + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanOrEqualToTest.swift; sourceTree = ""; }; + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanOrEqualToTest.swift; sourceTree = ""; }; + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeEmptyTest.m; sourceTree = ""; }; + 1FA0C3FE1E30B14500623165 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToTest.swift; sourceTree = ""; }; + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleEnvironment.swift; sourceTree = ""; }; + 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotificationTest.swift; sourceTree = ""; }; + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotification.swift; sourceTree = ""; }; + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionRecorder.swift; sourceTree = ""; }; + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdapterProtocols.swift; sourceTree = ""; }; + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleXCTestHandler.swift; sourceTree = ""; }; + 1FD8CD081968AB07008ED995 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + 1FD8CD091968AB07008ED995 /* Expectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expectation.swift; sourceTree = ""; }; + 1FD8CD0A1968AB07008ED995 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailureMessage.swift; sourceTree = ""; }; + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOf.swift; sourceTree = ""; }; + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeAKindOf.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseTo.swift; sourceTree = ""; }; + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmpty.swift; sourceTree = ""; }; + 1FD8CD111968AB07008ED995 /* BeginWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeginWith.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThanOrEqualTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeIdenticalTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThanOrEqual.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD171968AB07008ED995 /* BeLogical.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLogical.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD181968AB07008ED995 /* BeNil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeNil.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1A1968AB07008ED995 /* Contain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Contain.swift; sourceTree = ""; }; + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWith.swift; sourceTree = ""; }; + 1FD8CD1C1968AB07008ED995 /* Equal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Equal.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = ""; }; + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = ""; }; + 1FD8CD261968AB07008ED995 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = ""; }; + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = ""; }; + 1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = ""; }; + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionDispatcher.swift; sourceTree = ""; }; + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpectationMessage.swift; sourceTree = ""; }; + 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowErrorTest.swift; sourceTree = ""; }; + 29EA59651B551EE6002D767E /* ThrowError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowError.swift; sourceTree = ""; }; + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseProvider.swift; sourceTree = ""; }; + 472FD1341B9E085700C7B8DA /* HaveCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCount.swift; sourceTree = ""; }; + 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCountTest.swift; sourceTree = ""; }; + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCountTest.m; sourceTree = ""; }; + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = ""; }; + 7A0A26221E7F52360092A34E /* ToSucceed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceed.swift; sourceTree = ""; }; + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceedTest.swift; sourceTree = ""; }; + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfying.swift; sourceTree = ""; }; + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfyingTest.m; sourceTree = ""; }; + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfyingTest.swift; sourceTree = ""; }; + 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOfTest.swift; sourceTree = ""; }; + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOf.swift; sourceTree = ""; }; + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAnyOfTest.m; sourceTree = ""; }; + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcStringersTest.m; sourceTree = ""; }; + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertion.swift; sourceTree = ""; }; + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCUserDescriptionTest.m; sourceTree = ""; }; + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDescriptionTest.swift; sourceTree = ""; }; + A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAllOfTest.swift; sourceTree = ""; }; + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAllOfTest.m; sourceTree = ""; }; + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatisfyAllOf.swift; sourceTree = ""; }; + AE4BA9AC1C88DDB500B73906 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchError.swift; sourceTree = ""; }; + AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = ""; }; + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = ""; }; + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = ""; }; + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = ""; }; + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = ""; }; + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_excServer.h; sourceTree = ""; }; + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DSL+Wait.swift"; sourceTree = ""; }; + DD72EC631A93874A002F7651 /* AllPassTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPassTest.swift; sourceTree = ""; }; + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToObjectTest.swift; sourceTree = ""; }; + DDB1BC781A92235600F743C3 /* AllPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPass.swift; sourceTree = ""; }; + DDB4D5EC19FE43C200E9D9FE /* Match.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Match.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchTest.swift; sourceTree = ""; }; + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAllPassTest.m; sourceTree = ""; }; + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+Register.m"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F1A74251940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74311940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA9195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB4195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F14FB61194180A7009F2A08 /* Helpers */ = { + isa = PBXGroup; + children = ( + 1F14FB63194180C5009F2A08 /* utils.swift */, + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */, + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */, + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */, + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */, + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */, + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */, + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */, + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */, + ); + name = NimbleObjectiveC; + path = Sources/NimbleObjectiveC; + sourceTree = ""; + }; + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */, + ); + path = NonObjectiveC; + sourceTree = ""; + }; + 1F1A741F1940169200FFFC47 = { + isa = PBXGroup; + children = ( + 1F2752D119445B8400052A26 /* README.md */, + 1F1A742B1940169200FFFC47 /* Nimble */, + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */, + 1F1A74381940169200FFFC47 /* NimbleTests */, + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */, + 1F1A742A1940169200FFFC47 /* Products */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + usesTabs = 0; + }; + 1F1A742A1940169200FFFC47 /* Products */ = { + isa = PBXGroup; + children = ( + 1F1A74291940169200FFFC47 /* Nimble.framework */, + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */, + 1F925EAD195C0D6300ED456B /* Nimble.framework */, + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */, + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */, + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 1F1A742B1940169200FFFC47 /* Nimble */ = { + isa = PBXGroup; + children = ( + 1FD8CD041968AB07008ED995 /* Adapters */, + 1FD8CD081968AB07008ED995 /* DSL.swift */, + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */, + 1FD8CD091968AB07008ED995 /* Expectation.swift */, + 1FD8CD0A1968AB07008ED995 /* Expression.swift */, + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */, + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */, + 1F1A742D1940169200FFFC47 /* Info.plist */, + 1FD8CD0C1968AB07008ED995 /* Matchers */, + 1F1A742E1940169200FFFC47 /* Nimble.h */, + 1FD8CD241968AB07008ED995 /* Utils */, + ); + name = Nimble; + path = Sources/Nimble; + sourceTree = ""; + }; + 1F1A74381940169200FFFC47 /* NimbleTests */ = { + isa = PBXGroup; + children = ( + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */, + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */, + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */, + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */, + 1FFD729A1963FC8200CD29A2 /* objc */, + 1F14FB61194180A7009F2A08 /* Helpers */, + 1F925EE3195C11B000ED456B /* Matchers */, + 1F1A74391940169200FFFC47 /* Supporting Files */, + ); + name = NimbleTests; + path = Tests/NimbleTests; + sourceTree = ""; + }; + 1F1A74391940169200FFFC47 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 1F1A743A1940169200FFFC47 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1F925EE3195C11B000ED456B /* Matchers */ = { + isa = PBXGroup; + children = ( + DD72EC631A93874A002F7651 /* AllPassTest.swift */, + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */, + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */, + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */, + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */, + 1F925EFB195C186800ED456B /* BeginWithTest.swift */, + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */, + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */, + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */, + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */, + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */, + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */, + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */, + 1F925EF8195C175000ED456B /* BeNilTest.swift */, + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */, + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */, + 1F925F01195C189500ED456B /* ContainTest.swift */, + 1F925EFE195C187600ED456B /* EndWithTest.swift */, + 1F925F04195C18B700ED456B /* EqualTest.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 */, + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */, + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD041968AB07008ED995 /* Adapters */ = { + isa = PBXGroup; + children = ( + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */, + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */, + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */, + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */, + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */, + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */, + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */, + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */, + ); + path = Adapters; + sourceTree = ""; + }; + 1FD8CD0C1968AB07008ED995 /* Matchers */ = { + isa = PBXGroup; + children = ( + DDB1BC781A92235600F743C3 /* AllPass.swift */, + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */, + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */, + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */, + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */, + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */, + 1FD8CD111968AB07008ED995 /* BeginWith.swift */, + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */, + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */, + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */, + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */, + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */, + 1FD8CD171968AB07008ED995 /* BeLogical.swift */, + 1FD8CD181968AB07008ED995 /* BeNil.swift */, + 1F91DD301C74BF61002C309F /* BeVoid.swift */, + 1FD8CD1A1968AB07008ED995 /* Contain.swift */, + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */, + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */, + 1FD8CD1C1968AB07008ED995 /* Equal.swift */, + 472FD1341B9E085700C7B8DA /* HaveCount.swift */, + DDB4D5EC19FE43C200E9D9FE /* Match.swift */, + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */, + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */, + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */, + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */, + 1FA0C3FE1E30B14500623165 /* Predicate.swift */, + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */, + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */, + 29EA59651B551EE6002D767E /* ThrowError.swift */, + 7A0A26221E7F52360092A34E /* ToSucceed.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD241968AB07008ED995 /* Utils */ = { + isa = PBXGroup; + children = ( + 1FD8CD251968AB07008ED995 /* Functional.swift */, + 1FD8CD261968AB07008ED995 /* Async.swift */, + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */, + 1FD8CD281968AB07008ED995 /* Stringers.swift */, + AE4BA9AC1C88DDB500B73906 /* Errors.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 1FFD729A1963FC8200CD29A2 /* objc */ = { + isa = PBXGroup; + children = ( + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */, + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */, + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */, + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */, + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */, + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */, + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */, + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */, + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */, + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */, + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */, + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */, + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */, + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */, + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */, + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */, + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */, + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */, + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = { + isa = PBXGroup; + children = ( + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */, + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */, + ); + name = "Carthage-Checkouts"; + path = Carthage/Checkouts; + sourceTree = ""; + }; + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */, + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */, + ); + name = CwlCatchException; + path = CwlCatchException/Sources; + sourceTree = ""; + }; + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */, + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */, + ); + name = CwlPreconditionTesting; + path = CwlPreconditionTesting/Sources; + sourceTree = ""; + }; + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */, + ); + path = CwlCatchException; + sourceTree = ""; + }; + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */ = { + isa = PBXGroup; + children = ( + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */, + CDFB6A211F7E07C600AD8CC7 /* include */, + ); + path = CwlCatchExceptionSupport; + sourceTree = ""; + }; + CDFB6A211F7E07C600AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */, + ); + path = include; + sourceTree = ""; + }; + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */, + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */, + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */, + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */, + CDFB6A2F1F7E082400AD8CC7 /* Mach */, + CDFB6A311F7E082400AD8CC7 /* Posix */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; + CDFB6A2F1F7E082400AD8CC7 /* Mach */ = { + isa = PBXGroup; + children = ( + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */, + ); + path = Mach; + sourceTree = ""; + }; + CDFB6A311F7E082400AD8CC7 /* Posix */ = { + isa = PBXGroup; + children = ( + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */, + ); + path = Posix; + sourceTree = ""; + }; + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = { + isa = PBXGroup; + children = ( + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */, + CDFB6A351F7E082400AD8CC7 /* include */, + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */, + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */, + ); + path = CwlMachBadInstructionHandler; + sourceTree = ""; + }; + CDFB6A351F7E082400AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */, + ); + path = include; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + 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 */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + 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; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F1A74281940169200FFFC47 /* Nimble-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */; + buildPhases = ( + 1F1A74241940169200FFFC47 /* Sources */, + 1F1A74251940169200FFFC47 /* Frameworks */, + 1F1A74261940169200FFFC47 /* Headers */, + 1F1A74271940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-iOS"; + productName = "Nimble-iOS"; + productReference = 1F1A74291940169200FFFC47 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */; + buildPhases = ( + 1F1A74301940169200FFFC47 /* Sources */, + 1F1A74311940169200FFFC47 /* Frameworks */, + 1F1A74321940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F1A74371940169200FFFC47 /* PBXTargetDependency */, + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */, + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */, + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */, + ); + name = "Nimble-iOSTests"; + productName = "Nimble-iOSTests"; + productReference = 1F1A74341940169200FFFC47 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */; + buildPhases = ( + 1F5DF1501BDCA0CE00C3A531 /* Sources */, + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */, + 1F5DF1521BDCA0CE00C3A531 /* Headers */, + 1F5DF1531BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-tvOS"; + productName = "Nimble-tvOS"; + productReference = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */; + buildPhases = ( + 1F5DF15A1BDCA0CE00C3A531 /* Sources */, + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */, + 1F5DF15C1BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */, + ); + name = "Nimble-tvOSTests"; + productName = "Nimble-tvOSTests"; + productReference = 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F925EAC195C0D6300ED456B /* Nimble-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */; + buildPhases = ( + 1F925EA8195C0D6300ED456B /* Sources */, + 1F925EA9195C0D6300ED456B /* Frameworks */, + 1F925EAA195C0D6300ED456B /* Headers */, + 1F925EAB195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-macOS"; + productName = "Nimble-macOS"; + productReference = 1F925EAD195C0D6300ED456B /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */; + buildPhases = ( + 1F925EB3195C0D6300ED456B /* Sources */, + 1F925EB4195C0D6300ED456B /* Frameworks */, + 1F925EB5195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */, + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */, + ); + name = "Nimble-macOSTests"; + productName = "Nimble-OSXTests"; + productReference = 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1F1A74201940169200FFFC47 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F925EAC195C0D6300ED456B; + }; + A8F2B2541E79A4AB005BDD17 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1F1A741F1940169200FFFC47; + productRefGroup = 1F1A742A1940169200FFFC47 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1F925EAC195C0D6300ED456B /* Nimble-macOS */, + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */, + 1F1A74281940169200FFFC47 /* Nimble-iOS */, + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */, + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */, + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */, + A8F2B2541E79A4AB005BDD17 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F1A74271940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74321940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1531BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15C1BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAB195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB5195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A8F2B2581E79A4B0005BDD17 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F1A74241940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */, + 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 */, + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */, + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */, + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */, + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */, + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */, + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 29EA59661B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */, + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */, + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */, + CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */, + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */, + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, + CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */, + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74301940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */, + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */, + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */, + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */, + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */, + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */, + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0A1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13B1B9E0CFE00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1501BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */, + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */, + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */, + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */, + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */, + 1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */, + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */, + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */, + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */, + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */, + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */, + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */, + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */, + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */, + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */, + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */, + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */, + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */, + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */, + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */, + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */, + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */, + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */, + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */, + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */, + CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */, + 1F5DF18C1BDCA0F500C3A531 /* Async.swift in Sources */, + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */, + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */, + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */, + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */, + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */, + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */, + CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, + 1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */, + 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15A1BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */, + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */, + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */, + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */, + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */, + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */, + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */, + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */, + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */, + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */, + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */, + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */, + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */, + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */, + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */, + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */, + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */, + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */, + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */, + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */, + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */, + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */, + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */, + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */, + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */, + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */, + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */, + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */, + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */, + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */, + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */, + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */, + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */, + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */, + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */, + 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 */, + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */, + CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */, + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 6CAEDD0C1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */, + CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */, + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */, + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */, + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */, + CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */, + CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA8195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */, + 1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */, + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */, + 1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */, + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */, + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */, + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */, + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */, + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */, + 29EA59671B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */, + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */, + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */, + CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */, + CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */, + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */, + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, + CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */, + 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB3195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.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 */, + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAC19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59641B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0B1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13A1B9E0A9F00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1F1A74371940169200FFFC47 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */; + }; + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */; + targetProxy = 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */; + }; + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */; + }; + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */; + }; + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F1A743D1940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1F1A743E1940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 1F1A74401940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + "$(inherited)", + ); + 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; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74411940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + ); + 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"; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 1F1A74431940169200FFFC47 /* Debug */ = { + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_CODE_SIGN_FLAGS = "--verbose"; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74441940169200FFFC47 /* Release */ = { + 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"; + 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"; + }; + name = Release; + }; + 1F5DF1661BDCA0CE00C3A531 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 1F5DF1671BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + 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 = ( + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F5DF1681BDCA0CE00C3A531 /* Debug */ = { + 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"; + 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; + }; + name = Debug; + }; + 1F5DF1691BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + 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"; + 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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F925EC1195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + 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 = { + 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)", + "$(inherited)", + ); + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + 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; + }; + name = Release; + }; + 1F925EC4195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F925EC5195C0D6300ED456B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + A8F2B2551E79A4AB005BDD17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Debug; + }; + A8F2B2561E79A4AB005BDD17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A743D1940169200FFFC47 /* Debug */, + 1F1A743E1940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74401940169200FFFC47 /* Debug */, + 1F1A74411940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74431940169200FFFC47 /* Debug */, + 1F1A74441940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1661BDCA0CE00C3A531 /* Debug */, + 1F5DF1671BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1681BDCA0CE00C3A531 /* Debug */, + 1F5DF1691BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC1195C0D6300ED456B /* Debug */, + 1F925EC2195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC4195C0D6300ED456B /* Debug */, + 1F925EC5195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8F2B2551E79A4AB005BDD17 /* Debug */, + A8F2B2561E79A4AB005BDD17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F1A74201940169200FFFC47 /* Project object */; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..80405c9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..d640838 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..c45d780 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package.swift new file mode 100644 index 0000000..8d0b745 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:3.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package@swift-4.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package@swift-4.swift new file mode 100644 index 0000000..740b842 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Package@swift-4.swift @@ -0,0 +1,22 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + products: [ + .library(name: "Nimble", targets: ["Nimble"]), + ], + targets: [ + .target( + name: "Nimble", + dependencies: [] + ), + .testTarget( + name: "NimbleTests", + dependencies: ["Nimble"], + exclude: ["objc"] + ), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/README.md new file mode 100644 index 0000000..19c562f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/README.md @@ -0,0 +1,1764 @@ +# Nimble + +[![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) +[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble) + +Use Nimble to express the expected outcomes of Swift +or Objective-C expressions. Inspired by +[Cedar](https://github.com/pivotal/cedar). + +```swift +// Swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + +# How to Use Nimble + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest) +- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto) + - [Custom Failure Messages](#custom-failure-messages) + - [Type Safety](#type-safety) + - [Operator Overloads](#operator-overloads) + - [Lazily Computed Values](#lazily-computed-values) + - [C Primitives](#c-primitives) + - [Asynchronous Expectations](#asynchronous-expectations) + - [Objective-C Support](#objective-c-support) + - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand) +- [Built-in Matcher Functions](#built-in-matcher-functions) + - [Type Checking](#type-checking) + - [Equivalence](#equivalence) + - [Identity](#identity) + - [Comparisons](#comparisons) + - [Types/Classes](#typesclasses) + - [Truthiness](#truthiness) + - [Swift Assertions](#swift-assertions) + - [Swift Error Handling](#swift-error-handling) + - [Exceptions](#exceptions) + - [Collection Membership](#collection-membership) + - [Strings](#strings) + - [Collection Elements](#collection-elements) + - [Collection Count](#collection-count) + - [Notifications](#notifications) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) + - [Custom Validation](#custom-validation) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [PredicateResult](#predicateresult) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Basic Customization](#basic-customization) + - [Full Customization](#full-customization) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) + - [Migrating from the Old Matcher API](#migrating-from-the-old-matcher-api) + - [Minimal Step - Use `.predicate`](#minimal-step---use-predicate) + - [Convert to use `Predicate` Type with Old Matcher Constructor](#convert-to-use-predicate-type-with-old-matcher-constructor) + - [Convert to `Predicate` Type with Preferred Constructor](#convert-to-predicate-type-with-preferred-constructor) + - [Deprecation Roadmap](#deprecation-roadmap) +- [Installing Nimble](#installing-nimble) + - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule) + - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods) + - [Using Nimble without XCTest](#using-nimble-without-xctest) + + + +# Some Background: Expressing Outcomes Using Assertions in XCTest + +Apple's Xcode includes the XCTest framework, which provides +assertion macros to test whether code behaves properly. +For example, to assert that `1 + 1 = 2`, XCTest has you write: + +```swift +// Swift + +XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two") +``` + +Or, in Objective-C: + +```objc +// Objective-C + +XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two"); +``` + +XCTest assertions have a couple of drawbacks: + +1. **Not enough macros.** There's no easy way to assert that a string + contains a particular substring, or that a number is less than or + equal to another. +2. **It's hard to write asynchronous tests.** XCTest forces you to write + a lot of boilerplate code. + +Nimble addresses these concerns. + +# Nimble: Expectations Using `expect(...).to` + +Nimble allows you to express expectations using a natural, +easily understood language: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).to(equal("Squee!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).to(equal(@"Squee!")); +``` + +> The `expect` function autocompletes to include `file:` and `line:`, + but these parameters are optional. Use the default values to have + Xcode highlight the correct line when an expectation is not met. + +To perform the opposite expectation--to assert something is *not* +equal--use `toNot` or `notTo`: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).toNot(equal("Oh, hello there!")) +expect(seagull.squawk).notTo(equal("Oh, hello there!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).toNot(equal(@"Oh, hello there!")); +expect(seagull.squawk).notTo(equal(@"Oh, hello there!")); +``` + +## Custom Failure Messages + +Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text: + +```swift +// Swift + +expect(1 + 1).to(equal(3)) +// failed - expected to equal <3>, got <2> + +expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded") +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3>, got <2> +``` + +Or the *WithDescription version in Objective-C: + +```objc +// Objective-C + +@import Nimble; + +expect(@(1+1)).to(equal(@3)); +// failed - expected to equal <3.0000>, got <2.0000> + +expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded"); +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3.0000>, got <2.0000> +``` + +## Type Safety + +Nimble makes sure you don't compare two types that don't match: + +```swift +// Swift + +// Does not compile: +expect(1 + 1).to(equal("Squee!")) +``` + +> Nimble uses generics--only available in Swift--to ensure + type correctness. That means type checking is + not available when using Nimble in Objective-C. :sob: + +## Operator Overloads + +Tired of so much typing? With Nimble, you can use overloaded operators +like `==` for equivalence, or `>` for comparisons: + +```swift +// Swift + +// Passes if squawk does not equal "Hi!": +expect(seagull.squawk) != "Hi!" + +// Passes if 10 is greater than 2: +expect(10) > 2 +``` + +> Operator overloads are only available in Swift, so you won't be able + to use this syntax in Objective-C. :broken_heart: + +## Lazily Computed Values + +The `expect` function doesn't evaluate the value it's given until it's +time to match. So Nimble can test whether an expression raises an +exception once evaluated: + +```swift +// Swift + +// Note: Swift currently doesn't have exceptions. +// Only Objective-C code can raise exceptions +// that Nimble will catch. +// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064) +let exception = NSException( + name: NSInternalInconsistencyException, + reason: "Not enough fish in the sea.", + userInfo: ["something": "is fishy"]) +expect { exception.raise() }.to(raiseException()) + +// Also, you can customize raiseException to be more specific +expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException)) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea")) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea", + userInfo: ["something": "is fishy"])) +``` + +Objective-C works the same way, but you must use the `expectAction` +macro when making an expectation on an expression that has no return +value: + +```objc +// Objective-C + +NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Not enough fish in the sea." + userInfo:nil]; +expectAction(^{ [exception raise]; }).to(raiseException()); + +// Use the property-block syntax to be more specific. +expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException)); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea")); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea"). + userInfo(@{@"something": @"is fishy"})); + +// You can also pass a block for custom matching of the raised exception +expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(NSInternalInconsistencyException)); +})); +``` + +## C Primitives + +Some testing frameworks make it hard to test primitive C values. +In Nimble, it just works: + +```swift +// Swift + +let actual: CInt = 1 +let expectedValue: CInt = 1 +expect(actual).to(equal(expectedValue)) +``` + +In fact, Nimble uses type inference, so you can write the above +without explicitly specifying both types: + +```swift +// Swift + +expect(1 as CInt).to(equal(1)) +``` + +> In Objective-C, Nimble only supports Objective-C objects. To + make expectations on primitive C values, wrap then in an object + literal: + +```objc +expect(@(1 + 1)).to(equal(@2)); +``` + +## Asynchronous Expectations + +In Nimble, it's easy to make expectations on values that are updated +asynchronously. Just use `toEventually` or `toEventuallyNot`: + +```swift +// Swift 3.0 and later + +DispatchQueue.main.async { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```swift +// Swift 2.3 and earlier + +dispatch_async(dispatch_get_main_queue()) { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```objc +// Objective-C + +dispatch_async(dispatch_get_main_queue(), ^{ + [ocean add:@"dolphins"]; + [ocean add:@"whales"]; +}); +expect(ocean).toEventually(contain(@"dolphins", @"whales")); +``` + +Note: toEventually triggers its polls on the main thread. Blocking the main +thread will cause Nimble to stop the run loop. This can cause test pollution +for whatever incomplete code that was running on the main thread. Blocking the +main thread can be caused by blocking IO, calls to sleep(), deadlocks, and +synchronous IPC. + +In the above example, `ocean` is constantly re-evaluated. If it ever +contains dolphins and whales, the expectation passes. If `ocean` still +doesn't contain them, even after being continuously re-evaluated for one +whole second, the expectation fails. + +Sometimes it takes more than a second for a value to update. In those +cases, use the `timeout` parameter: + +```swift +// Swift + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).toEventually(contain("starfish"), timeout: 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) +``` + +```objc +// Objective-C + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).withTimeout(3).toEventually(contain(@"starfish")); +``` + +You can also provide a callback by using the `waitUntil` function: + +```swift +// Swift + +waitUntil { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +Note: `waitUntil` triggers its timeout code on the main thread. Blocking the main +thread will cause Nimble to stop the run loop to continue. This can cause test +pollution for whatever incomplete code that was running on the main thread. +Blocking the main thread can be caused by blocking IO, calls to sleep(), +deadlocks, and synchronous IPC. + +In some cases (e.g. when running on slower machines) it can be useful to modify +the default timeout and poll interval values. This can be done as follows: + +```swift +// Swift + +// Increase the global timeout to 5 seconds: +Nimble.AsyncDefaults.Timeout = 5 + +// Slow the polling interval to 0.1 seconds: +Nimble.AsyncDefaults.PollInterval = 0.1 +``` + +## Objective-C Support + +Nimble has full support for Objective-C. However, there are two things +to keep in mind when using Nimble in Objective-C: + +1. All parameters passed to the `expect` function, as well as matcher + functions like `equal`, must be Objective-C objects or can be converted into + an `NSObject` equivalent: + + ```objc + // Objective-C + + @import Nimble; + + expect(@(1 + 1)).to(equal(@2)); + expect(@"Hello world").to(contain(@"world")); + + // Boxed as NSNumber * + expect(2).to(equal(2)); + expect(1.2).to(beLessThan(2.0)); + expect(true).to(beTruthy()); + + // Boxed as NSString * + expect("Hello world").to(equal("Hello world")); + + // Boxed as NSRange + expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10))); + ``` + +2. To make an expectation on an expression that does not return a value, + such as `-[NSException raise]`, use `expectAction` instead of + `expect`: + + ```objc + // Objective-C + + expectAction(^{ [exception raise]; }).to(raiseException()); + ``` + +The following types are currently converted to an `NSObject` type: + + - **C Numeric types** are converted to `NSNumber *` + - `NSRange` is converted to `NSValue *` + - `char *` is converted to `NSString *` + +For the following matchers: + +- `equal` +- `beGreaterThan` +- `beGreaterThanOrEqual` +- `beLessThan` +- `beLessThanOrEqual` +- `beCloseTo` +- `beTrue` +- `beFalse` +- `beTruthy` +- `beFalsy` +- `haveCount` + +If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues). + +## Disabling Objective-C Shorthand + +Nimble provides a shorthand for expressing expectations using the +`expect` function. To disable this shorthand in Objective-C, define the +`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before +importing Nimble: + +```objc +#define NIMBLE_DISABLE_SHORT_SYNTAX 1 + +@import Nimble; + +NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!")); +``` + +> Disabling the shorthand is useful if you're testing functions with + names that conflict with Nimble functions, such as `expect` or + `equal`. If that's not the case, there's no point in disabling the + shorthand. + +# Built-in Matcher Functions + +Nimble includes a wide variety of matcher functions. + +## Type Checking + +Nimble supports checking the type membership of any kind of object, whether +Objective-C conformant or not: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// The following tests pass +expect(1).to(beAKindOf(Int.self)) +expect("turtle").to(beAKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beAKindOf(SomeProtocol.self)) +expect(classObject).to(beAKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beAKindOf(SomeProtocol.self)) +expect(structObject).to(beAKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAKindOf(SomeClassConformingToProtocol.self)) +``` + +```objc +// Objective-C + +// The following tests pass +NSMutableArray *array = [NSMutableArray array]; +expect(array).to(beAKindOf([NSArray class])); +expect(@1).toNot(beAKindOf([NSNull class])); +``` + +Objects can be tested for their exact types using the `beAnInstanceOf` matcher: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only +// passes if the object is the EXACT type requested. The following +// tests pass -- note its behavior when working in an inheritance hierarchy. +expect(1).to(beAnInstanceOf(Int.self)) +expect("turtle").to(beAnInstanceOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self)) +``` + +## Equivalence + +```swift +// Swift + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) +expect(actual) == expected + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +expect(actual) != expected +``` + +```objc +// Objective-C + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +``` + +Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`. +`equal` will always fail when used to compare one or more `nil` values. + +## Identity + +```swift +// Swift + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)) +expect(actual) === expected + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)) +expect(actual) !== expected +``` + +It is important to remember that `beIdenticalTo` only makes sense when comparing +types with reference semantics, which have a notion of identity. In Swift, +that means types that are defined as a `class`. + +This matcher will not work when comparing types with value semantics such as +those defined as a `struct` or `enum`. If you need to compare two value types, +consider what it means for instances of your type to be identical. This may mean +comparing individual properties or, if it makes sense to do so, conforming your type +to `Equatable` and using Nimble's equivalence matchers instead. + + +```objc +// Objective-C + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)); + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)); +``` + +## Comparisons + +```swift +// Swift + +expect(actual).to(beLessThan(expected)) +expect(actual) < expected + +expect(actual).to(beLessThanOrEqualTo(expected)) +expect(actual) <= expected + +expect(actual).to(beGreaterThan(expected)) +expect(actual) > expected + +expect(actual).to(beGreaterThanOrEqualTo(expected)) +expect(actual) >= expected +``` + +```objc +// Objective-C + +expect(actual).to(beLessThan(expected)); +expect(actual).to(beLessThanOrEqualTo(expected)); +expect(actual).to(beGreaterThan(expected)); +expect(actual).to(beGreaterThanOrEqualTo(expected)); +``` + +> Values given to the comparison matchers above must implement + `Comparable`. + +Because of how computers represent floating point numbers, assertions +that two floating point numbers be equal will sometimes fail. To express +that two numbers should be close to one another within a certain margin +of error, use `beCloseTo`: + +```swift +// Swift + +expect(actual).to(beCloseTo(expected, within: delta)) +``` + +```objc +// Objective-C + +expect(actual).to(beCloseTo(expected).within(delta)); +``` + +For example, to assert that `10.01` is close to `10`, you can write: + +```swift +// Swift + +expect(10.01).to(beCloseTo(10, within: 0.1)) +``` + +```objc +// Objective-C + +expect(@(10.01)).to(beCloseTo(@10).within(0.1)); +``` + +There is also an operator shortcut available in Swift: + +```swift +// Swift + +expect(actual) ≈ expected +expect(actual) ≈ (expected, delta) + +``` +(Type option+x to get `≈` on a U.S. keyboard) + +The former version uses the default delta of 0.0001. Here is yet another way to do this: + +```swift +// Swift + +expect(actual) ≈ expected ± delta +expect(actual) == expected ± delta + +``` +(Type option+shift+= to get `±` on a U.S. keyboard) + +If you are comparing arrays of floating point numbers, you'll find the following useful: + +```swift +// Swift + +expect([0.0, 2.0]) ≈ [0.0001, 2.0001] +expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1)) + +``` + +> Values given to the `beCloseTo` matcher must be coercable into a + `Double`. + +## Types/Classes + +```swift +// Swift + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)) + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)) +``` + +```objc +// Objective-C + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)); + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)); +``` + +> Instances must be Objective-C objects: subclasses of `NSObject`, + or Swift objects bridged to Objective-C with the `@objc` prefix. + +For example, to assert that `dolphin` is a kind of `Mammal`: + +```swift +// Swift + +expect(dolphin).to(beAKindOf(Mammal)) +``` + +```objc +// Objective-C + +expect(dolphin).to(beAKindOf([Mammal class])); +``` + +> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to + test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`. + +## Truthiness + +```swift +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()) + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()) + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()) + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()) + +// Passes if 'actual' is nil: +expect(actual).to(beNil()) +``` + +```objc +// Objective-C + +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()); + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()); + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()); + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()); + +// Passes if 'actual' is nil: +expect(actual).to(beNil()); +``` + +## Swift Assertions + +If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an assertion, +// such as by calling 'fatalError()' or if a precondition fails: +expect { try somethingThatThrows() }.to(throwAssertion()) +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing an NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the code after the precondition check is not run: +var reachedPoint1 = false +var reachedPoint2 = false +expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true +}.to(throwAssertion()) + +expect(reachedPoint1) == true +expect(reachedPoint2) == false +``` + +Notes: + +* This feature is only available in Swift. +* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_. +* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration. + +## Swift Error Handling + +If you're using Swift 2.0 or newer, you can use the `throwError` matcher to check if an error is thrown. + +Note: +The following code sample references the `Swift.Error` protocol. +This is `Swift.ErrorProtocol` in versions of Swift prior to version 3.0. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an 'Error': +expect { try somethingThatThrows() }.to(throwError()) + +// Passes if 'somethingThatThrows()' throws an error within a particular domain: +expect { try somethingThatThrows() }.to(throwError { (error: Error) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if 'somethingThatThrows()' throws a particular error enum case: +expect { try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if 'somethingThatThrows()' throws an error of a particular type: +expect { try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +When working directly with `Error` values, using the `matchError` matcher +allows you to perform certain checks on the error itself without having to +explicitly cast the error. + +The `matchError` matcher allows you to check whether or not the error: + +- is the same _type_ of error you are expecting. +- represents a particular error value that you are expecting. + +This can be useful when using `Result` or `Promise` types, for example. + +```swift +// Swift + +let actual: Error = ... + +// Passes if 'actual' represents any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.self)) + +// Passes if 'actual' represents the case 'timeout' from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.timeout)) + +// Passes if 'actual' contains an NSError equal to the one provided: +expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil))) +``` + +Note: This feature is only available in Swift. + +## Exceptions + +```swift +// Swift + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name: +expect(actual).to(raiseException(named: name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException(named: name, reason: reason)) + +// Passes if 'actual' raises an exception which passes expectations defined in the given closure: +// (in this case, if the exception's name begins with "a r") +expect { exception.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(beginWith("a r")) +}) +``` + +```objc +// Objective-C + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name +expect(actual).to(raiseException().named(name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException().named(name).reason(reason)) + +// Passes if 'actual' raises an exception and it passes expectations defined in the given block: +// (in this case, if name begins with "a r") +expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(@"a r")); +})); +``` + +Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)). +Only Objective-C code can raise exceptions that Nimble will catch. + +## Collection Membership + +```swift +// Swift + +// Passes if all of the expected values are members of 'actual': +expect(actual).to(contain(expected...)) + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()) +``` + +```objc +// Objective-C + +// Passes if expected is a member of 'actual': +expect(actual).to(contain(expected)); + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()); +``` + +> In Swift `contain` takes any number of arguments. The expectation + passes if all of them are members of the collection. In Objective-C, + `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27). + +For example, to assert that a list of sea creature names contains +"dolphin" and "starfish": + +```swift +// Swift + +expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish")) +``` + +```objc +// Objective-C + +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin")); +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish")); +``` + +> `contain` and `beEmpty` expect collections to be instances of + `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements. + +To test whether a set of elements is present at the beginning or end of +an ordered collection, use `beginWith` and `endWith`: + +```swift +// Swift + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected...)) + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected...)) +``` + +```objc +// Objective-C + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected)); + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected)); +``` + +> `beginWith` and `endWith` expect collections to be instances of + `NSArray`, or ordered Swift collections composed of `Equatable` + elements. + + Like `contain`, in Objective-C `beginWith` and `endWith` only support + a single argument [for now](https://github.com/Quick/Nimble/issues/27). + +For code that returns collections of complex objects without a strict +ordering, there is the `containElementSatisfying` matcher: + +```swift +// Swift + +struct Turtle { + let color: String +} + +let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "green" +})) +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "blue" +}, "that is a turtle with color 'blue'")) + +// The second matcher will incorporate the provided string in the error message +// should it fail +``` + +```objc +// Objective-C + +@interface Turtle : NSObject +@property (nonatomic, readonly, nonnull) NSString *color; +@end + +@implementation Turtle +@end + +NSArray * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(substring)) + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)) + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)) + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()) + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(expected)); + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)); + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)); + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()); + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +## Collection Elements + +Nimble provides a means to check that all elements of a collection pass a given expectation. + +### Swift + +In Swift, the collection must be an instance of a type conforming to +`Sequence`. + +```swift +// Swift + +// Providing a custom function: +expect([1, 2, 3, 4]).to(allPass { $0! < 5 }) + +// Composing the expectation with another matcher: +expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) +``` + +### Objective-C + +In Objective-C, the collection must be an instance of a type which implements +the `NSFastEnumeration` protocol, and whose elements are instances of a type +which subclasses `NSObject`. + +Additionally, unlike in Swift, there is no override to specify a custom +matcher function. + +```objc +// Objective-C + +expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@5))); +``` + +## Collection Count + +```swift +// Swift + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +For Swift, the actual value must be an instance of a type conforming to `Collection`. +For example, instances of `Array`, `Dictionary`, or `Set`. + +For Objective-C, the actual value must be one of the following classes, or their subclasses: + + - `NSArray`, + - `NSDictionary`, + - `NSSet`, or + - `NSHashTable`. + +## Notifications + +```swift +// Swift +let testNotification = Notification(name: "Foo", object: nil) + +// passes if the closure in expect { ... } posts a notification to the default +// notification center. +expect { + NotificationCenter.default.postNotification(testNotification) +}.to(postNotifications(equal([testNotification])) + +// 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)) +``` + +> This matcher is only available in Swift. + +## Matching a value to any of a group of matchers + +```swift +// Swift + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7))) + +// in Swift you also have the option to use the || operator to achieve a similar function +expect(82).to(beLessThan(50) || beGreaterThan(80)) +``` + +```objc +// Objective-C + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7))) +``` + +Note: This matcher allows you to chain any number of matchers together. This provides flexibility, + but if you find yourself chaining many matchers together in one test, consider whether you + could instead refactor that single test into multiple, more precisely focused tests for + better coverage. + +## Custom Validation + +```swift +// Swift + +// passes if .succeeded is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).to(succeed()) + +// passes if .failed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).notTo(succeed()) +``` + +The `String` provided with `.failed()` is shown when the test fails. + +When using `toEventually()` be careful not to make state changes or run process intensive code since this closure will be ran many times. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `Predicate` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> Predicate { + // Can be shortened to: + // Predicate { actual in ... } + // + // But shown with types here for clarity. + return Predicate { (actual: Expression) throws -> PredicateResult in + let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>") + if let actualValue = try actualExpression.evaluate() { + return PredicateResult( + bool: actualValue == expectedValue!, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} +``` + +The return value of a `Predicate` closure is a `PredicateResult` that indicates +whether the actual value matches the expectation and what error message to +display on failure. + +> The actual `equal` matcher function does not match when + `expected` are nil; the example above has been edited for brevity. + +Since matchers are just Swift functions, you can define them anywhere: +at the top of your test file, in a file shared by all of your tests, or +in an Xcode project you distribute to others. + +> If you write a matcher you think everyone can use, consider adding it + to Nimble's built-in set of matchers by sending a pull request! Or + distribute it yourself via GitHub. + +For examples of how to write your own matchers, just check out the +[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers) +to see how Nimble's built-in set of matchers are implemented. You can +also check out the tips below. + +## PredicateResult + +`PredicateResult` is the return struct that `Predicate` return to indicate +success and failure. A `PredicateResult` is made up of two values: +`PredicateStatus` and `ExpectationMessage`. + +Instead of a boolean, `PredicateStatus` captures a trinary set of values: + +```swift +// Swift + +public enum PredicateStatus { +// The predicate "passes" with the given expression +// eg - expect(1).to(equal(1)) +case matches + +// The predicate "fails" with the given expression +// eg - expect(1).toNot(equal(1)) +case doesNotMatch + +// The predicate never "passes" with the given expression, even if negated +// eg - expect(nil as Int?).toNot(equal(1)) +case fail + +// ... +} +``` + +Meanwhile, `ExpectationMessage` provides messaging semantics for error reporting. + +```swift +// Swift + +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// ... +} +``` + +Predicates should usually depend on either `.expectedActualValueTo(..)` or +`.fail(..)` when reporting errors. Special cases can be used for the other enum +cases. + +Finally, if your Predicate utilizes other Predicates, you can utilize +`.appended(details:)` and `.appended(message:)` methods to annotate an existing +error with more details. + +A common message to append is failing on nils. For that, `.appendedBeNilHint()` +can be used. + +## Lazy Evaluation + +`actualExpression` is a lazy, memoized closure around the value provided to the +`expect` function. The expression can either be a closure or a value directly +passed to `expect(...)`. In order to determine whether that value matches, +custom matchers should call `actualExpression.evaluate()`: + +```swift +// Swift + +public func beNil() -> Predicate { + // Predicate.simpleNilable(..) automatically generates ExpectationMessage for + // us based on the string we provide to it. Also, the 'Nilable' postfix indicates + // that this Predicate supports matching against nil actualExpressions, instead of + // always resulting in a PredicateStatus.fail result -- which is true for + // Predicate.simple(..) + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} +``` + +In the above example, `actualExpression` is not `nil` -- it is a closure +that returns a value. The value it returns, which is accessed via the +`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil` +matcher function returns `true`, indicating that the expectation passed. + +## Type Checking via Swift Generics + +Using Swift's generics, matchers can constrain the type of the actual value +passed to the `expect` function by modifying the return type. + +For example, the following matcher, `haveDescription`, only accepts actual +values that implement the `Printable` protocol. It checks their `description` +against the one provided to the matcher function, and passes if they are the same: + +```swift +// Swift + +public func haveDescription(description: String) -> Predicate { + return Predicate.simple("have description") { actual in + return PredicateStatus(bool: actual.evaluate().description == description) + } +} +``` + +## Customizing Failure Messages + +When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble +outputs the following failure message when an expectation fails: + +```swift +// where `message` is the first string argument and +// `actual` is the actual value received in `expect(..)` +"expected to \(message), got <\(actual)>" +``` + +You can customize this message by modifying the way you create a `Predicate`. + +### Basic Customization + +For slightly more complex error messaging, receive the created failure message +with `Predicate.define(..)`: + +```swift +// Swift + +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(bool: matches, message: msg) + } +} +``` + +In the example above, `msg` is defined based on the string given to +`Predicate.define`. The code looks akin to: + +```swift +// Swift + +let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedValue))>") +``` + +### Full Customization + +To fully customize the behavior of the Predicate, use the overload that expects +a `PredicateResult` to be returned. + +Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use: + +```swift +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// Emits standard error message with a custom actual value instead of the default. +// eg - "expected to , got " +case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + +// Emits standard error message without mentioning the actual value +// eg - "expected to " +case expectedTo(/* message: */ String) + +// ... +} +``` + +For matchers that compose other matchers, there are a handful of helper +functions to annotate messages. + +`appended(message: String)` is used to append to the original failure message: + +```swift +// produces "expected to be true, got (use beFalse() for inverse)" +// appended message do show up inline in Xcode. +.expectedActualValueTo("be true").appended(message: " (use beFalse() for inverse)") +``` + +For a more comprehensive message that spans multiple lines, use +`appended(details: String)` instead: + +```swift +// produces "expected to be true, got \n\nuse beFalse() for inverse\nor use beNil()" +// details do not show inline in Xcode, but do show up in test logs. +.expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()") +``` + +## 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 +custom matcher. The example below defines the class method +`+[NMBObjCMatcher 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) + } + } +} +``` + +The above allows you to use the matcher from Objective-C: + +```objc +// Objective-C + +expect(actual).to([NMBObjCMatcher beNilMatcher]()); +``` + +To make the syntax easier to use, define a C function that calls the +class method: + +```objc +// Objective-C + +FOUNDATION_EXPORT id beNil() { + return [NMBObjCMatcher beNilMatcher]; +} +``` + +### Properly Handling `nil` in Objective-C Matchers + +When supporting Objective-C, make sure you handle `nil` appropriately. +Like [Cedar](https://github.com/pivotal/cedar/issues/100), +**most matchers do not match with nil**. This is to bring prevent test +writers from being surprised by `nil` values where they did not expect +them. + +Nimble provides the `beNil` matcher function for test writer that want +to make expectations on `nil` objects: + +```objc +// Objective-C + +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. + +```swift + +public func beginWith(startingElement: T) -> NonNilMatcherFunc { + 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 + } +} + +extension NMBObjCMatcher { + public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.evaluate() + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } +} +``` + +## Migrating from the Old Matcher API + +Previously (`<7.0.0`), Nimble supported matchers via the following types: + +- `Matcher` +- `NonNilMatcherFunc` +- `MatcherFunc` + +All of those types have been replaced by `Predicate`. While migrating can be a +lot of work, Nimble currently provides several steps to aid migration of your +custom matchers: + +### Minimal Step - Use `.predicate` + +Nimble provides an extension to the old types that automatically naively +converts those types to the newer `Predicate`. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + 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 + }.predicate +} +``` + +This is the simpliest way to externally support `Predicate` which allows easier +composition than the old Nimble matcher interface, with minimal effort to change. + +### Convert to use `Predicate` Type with Old Matcher Constructor + +The second most convenient step is to utilize special constructors that +`Predicate` supports that closely align to the constructors of the old Nimble +matcher types. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} +``` + +This allows you to completely drop the old types from your code, although the +intended behavior may alter slightly to what is desired. + +### Convert to `Predicate` Type with Preferred Constructor + +Finally, you can convert to the native `Predicate` format using one of the +constructors not used to assist in the migration. + +### Deprecation Roadmap + +Nimble 7 introduces `Predicate` but will support the old types with warning +deprecations. A couple major releases of Nimble will remain backwards +compatible with the old matcher api, although new features may not be +backported. + +The deprecating plan is a 3 major versions removal. Which is as follows: + + 1. Introduce new `Predicate` API, deprecation warning for old matcher APIs. + (Nimble `v7.x.x`) + 2. Introduce warnings on migration-path features (`.predicate`, + `Predicate`-constructors with similar arguments to old API). (Nimble + `v8.x.x`) + 3. Remove old API. (Nimble `v9.x.x`) + + +# Installing Nimble + +> Nimble can be used on its own, or in conjunction with its sister + project, [Quick](https://github.com/Quick/Quick). To install both + Quick and Nimble, follow [the installation instructions in the Quick + Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md). + +Nimble can currently be installed in one of two ways: using CocoaPods, or with +git submodules. + +## Installing Nimble as a Submodule + +To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow +these 4 easy steps: + +1. Clone the Nimble repository +2. Add Nimble.xcodeproj to the Xcode workspace for your project +3. Link Nimble.framework to your test target +4. Start writing expectations! + +For more detailed instructions on each of these steps, +read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick). +Ignore the steps involving adding Quick to your project in order to +install just Nimble. + +## Installing Nimble via CocoaPods + +To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add +Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift +support for CocoaPods. + +```ruby +platform :ios, '8.0' + +source 'https://github.com/CocoaPods/Specs.git' + +# Whatever pods you need for your app go here + +target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do + use_frameworks! + pod 'Nimble', '~> 6.0.0' +end +``` + +Finally run `pod install`. + +## Using Nimble without XCTest + +Nimble is integrated with XCTest to allow it work well when used in Xcode test +bundles, however it can also be used in a standalone app. After installing +Nimble using one of the above methods, there are two additional steps required +to make this work. + +1. Create a custom assertion handler and assign an instance of it to the + global `NimbleAssertionHandler` variable. For example: + +```swift +class MyAssertionHandler : AssertionHandler { + func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) { + if (!assertion) { + print("Expectation failed: \(message.stringValue)") + } + } +} +``` +```swift +// Somewhere before you use any assertions +NimbleAssertionHandler = MyAssertionHandler() +``` + +2. Add a post-build action to fix an issue with the Swift XCTest support + library being unnecessarily copied into your app + * Edit your scheme in Xcode, and navigate to Build -> Post-actions + * Click the "+" icon and select "New Run Script Action" + * Open the "Provide build settings from" dropdown and select your target + * Enter the following script contents: +``` +rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib" +``` + +You can now use Nimble assertions in your code and handle failures as you see +fit. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift @@ -0,0 +1,17 @@ +import Foundation + +/// Protocol for the assertion handler that Nimble uses for all expectations. +public protocol AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) +} + +/// Global backing interface for assertions that Nimble creates. +/// Defaults to a private test handler that passes through to XCTest. +/// +/// If XCTest is not available, you must assign your own assertion handler +/// before using any matchers, otherwise Nimble will abort the program. +/// +/// @see AssertionHandler +public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in + return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() +}() diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift @@ -0,0 +1,19 @@ +/// AssertionDispatcher allows multiple AssertionHandlers to receive +/// assertion messages. +/// +/// @warning Does not fully dispatch if one of the handlers raises an exception. +/// This is possible with XCTest-based assertion handlers. +/// +public class AssertionDispatcher: AssertionHandler { + let handlers: [AssertionHandler] + + public init(handlers: [AssertionHandler]) { + self.handlers = handlers + } + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + for handler in handlers { + handler.assert(assertion, message: message, location: location) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift @@ -0,0 +1,100 @@ +import Foundation + +/// A data structure that stores information about an assertion when +/// AssertionRecorder is set as the Nimble assertion handler. +/// +/// @see AssertionRecorder +/// @see AssertionHandler +public struct AssertionRecord: CustomStringConvertible { + /// Whether the assertion succeeded or failed + public let success: Bool + /// The failure message the assertion would display on failure. + public let message: FailureMessage + /// The source location the expectation occurred on. + public let location: SourceLocation + + public var description: String { + return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" + } +} + +/// An AssertionHandler that silently records assertions that Nimble makes. +/// This is useful for testing failure messages for matchers. +/// +/// @see AssertionHandler +public class AssertionRecorder: AssertionHandler { + /// All the assertions that were captured by this recorder + public var assertions = [AssertionRecord]() + + public init() {} + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + assertions.append( + AssertionRecord( + success: assertion, + message: message, + location: location)) + } +} + +/// Allows you to temporarily replace the current Nimble assertion handler with +/// the one provided for the scope of the closure. +/// +/// Once the closure finishes, then the original Nimble assertion handler is restored. +/// +/// @see AssertionHandler +public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) { + let environment = NimbleEnvironment.activeInstance + let oldRecorder = environment.assertionHandler + let capturer = NMBExceptionCapture(handler: nil, finally: ({ + environment.assertionHandler = oldRecorder + })) + environment.assertionHandler = tempAssertionHandler + capturer.tryBlock { + try! closure() + } +} + +/// Captures expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about expectations +/// that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherFailingExpectations +public func gatherExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler + let recorder = AssertionRecorder() + let handlers: [AssertionHandler] + + if silently { + handlers = [recorder] + } else { + handlers = [recorder, previousRecorder] + } + + let dispatcher = AssertionDispatcher(handlers: handlers) + withAssertionHandler(dispatcher, closure: closure) + return recorder.assertions +} + +/// Captures failed expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about failed +/// expectations that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherExpectations +/// @see raiseException source for an example use case. +public func gatherFailingExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let assertions = gatherExpectations(silently: silently, closure: closure) + return assertions.filter { assertion in + !assertion.success + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..5e1afd5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,187 @@ +import Foundation + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +private func from(objcPredicate: NMBPredicate) -> Predicate { + return Predicate { actualExpression in + let result = objcPredicate.satisfies(({ try! actualExpression.evaluate() }), + location: actualExpression.location) + return result.toSwift() + } +} + +internal struct ObjCMatcherWrapper: Matcher { + let matcher: NMBMatcher + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.matches( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.doesNotMatch( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } +} + +// Equivalent to Expectation, but for Nimble's Objective-C interface +public class NMBExpectation: NSObject { + internal let _actualBlock: () -> NSObject? + internal var _negative: Bool + internal let _file: FileString + internal let _line: UInt + internal var _timeout: TimeInterval = 1.0 + + @objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) { + self._actualBlock = actualBlock + self._negative = negative + self._file = file + self._line = line + } + + private var expectValue: Expectation { + return expect(_file, line: _line) { + self._actualBlock() as NSObject? + } + } + + @objc public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + @objc public var to: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.to(from(objcPredicate: pred)) + } else { + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toNot(from(objcPredicate: pred)) + } else { + self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toNotWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var notTo: (NMBMatcher) -> Void { return toNot } + + @objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + @objc public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toNotEventually: (NMBMatcher) -> Void { + return toEventuallyNot + } + + @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { + return toEventuallyNotWithDescription + } + + @objc public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..0288b75 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,83 @@ +import Foundation + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +// swiftlint:disable line_length +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool +// swiftlint:enable line_length + +public class NMBObjCMatcher: NSObject, NMBMatcher { + let _match: MatcherBlock + let _doesNotMatch: MatcherBlock + let canMatchNil: Bool + + public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { + self.canMatchNil = canMatchNil + self._match = matcher + self._doesNotMatch = notMatcher + } + + public convenience init(matcher: @escaping MatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in + return !matcher(actualExpression, failureMessage) + })) + } + + public convenience init(matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, false) + }), notMatcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, true) + })) + } + + private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + do { + if !canMatchNil { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return false + } + } + } catch let error { + failureMessage.actualValue = "an unexpected error thrown: \(error)" + return false + } + return true + } + + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _match( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _doesNotMatch( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..e1b5432 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift @@ -0,0 +1,45 @@ +import Dispatch +import Foundation + +/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this +/// class' existence +internal class NimbleEnvironment { + static var activeInstance: NimbleEnvironment { + get { + let env = Thread.current.threadDictionary["NimbleEnvironment"] + if let env = env as? NimbleEnvironment { + return env + } else { + let newEnv = NimbleEnvironment() + self.activeInstance = newEnv + return newEnv + } + } + set { + Thread.current.threadDictionary["NimbleEnvironment"] = newValue + } + } + + // TODO: eventually migrate the global to this environment value + var assertionHandler: AssertionHandler { + get { return NimbleAssertionHandler } + set { NimbleAssertionHandler = newValue } + } + + var suppressTVOSAssertionWarning: Bool = false + var awaiter: Awaiter + + init() { + let timeoutQueue: DispatchQueue + if #available(OSX 10.10, *) { + timeoutQueue = DispatchQueue.global(qos: .userInitiated) + } else { + timeoutQueue = DispatchQueue.global(priority: .high) + } + + awaiter = Awaiter( + waitLock: AssertionWaitLock(), + asyncQueue: .main, + timeoutQueue: timeoutQueue) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..0ad8590 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,81 @@ +import Foundation +import XCTest + +/// Default handler for Nimble. This assertion handler passes failures along to +/// XCTest. +public class NimbleXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + recordFailure("\(message.stringValue)\n", location: location) + } + } +} + +/// Alternative handler for Nimble. This assertion handler passes failures along +/// to XCTest by attempting to reduce the failure message size. +public class NimbleShortXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + let msg: String + if let actual = message.actualValue { + msg = "got: \(actual) \(message.postfixActual)" + } else { + msg = "expected \(message.to) \(message.postfixMessage)" + } + recordFailure("\(msg)\n", location: location) + } + } +} + +/// Fallback handler in case XCTest is unavailable. This assertion handler will abort +/// the program if it is invoked. +class NimbleXCTestUnavailableHandler: AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") + } +} + +#if !SWIFT_PACKAGE +/// Helper class providing access to the currently executing XCTestCase instance, if any +@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { + @objc static let sharedInstance = CurrentTestCaseTracker() + + private(set) var currentTestCase: XCTestCase? + + @objc func testCaseWillStart(_ testCase: XCTestCase) { + currentTestCase = testCase + } + + @objc func testCaseDidFinish(_ testCase: XCTestCase) { + currentTestCase = nil + } +} +#endif + +func isXCTestAvailable() -> Bool { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // XCTest is weakly linked and so may not be present + return NSClassFromString("XCTestCase") != nil +#else + return true +#endif +} + +private func recordFailure(_ message: String, location: SourceLocation) { +#if SWIFT_PACKAGE + XCTFail("\(message)", file: location.file, line: location.line) +#else + if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { + #if swift(>=4) + let line = Int(location.line) + #else + let line = location.line + #endif + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..8f8d360 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) +// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy +class NSException {} +#endif + +// NOTE: This file is not intended to be included in the Xcode project. It +// is picked up by the Swift Package Manager during its build process. + +/// A dummy reimplementation of the `NMBExceptionCapture` class to serve +/// as a stand-in for build and runtime environments that don't support +/// Objective C. +internal class ExceptionCapture { + let finally: (() -> Void)? + + init(handler: ((NSException) -> Void)?, finally: (() -> Void)?) { + self.finally = finally + } + + func tryBlock(_ unsafeBlock: (() -> Void)) { + // We have no way of handling Objective C exceptions in Swift, + // so we just go ahead and run the unsafeBlock as-is + unsafeBlock() + + finally?() + } +} + +/// Compatibility with the actual Objective-C implementation +typealias NMBExceptionCapture = ExceptionCapture diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..e874136 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,116 @@ +import Dispatch +import Foundation + +private enum ErrorResult { + case exception(NSException) + case error(Error) + case none +} + +/// Only classes, protocols, methods, properties, and subscript declarations can be +/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style +/// asynchronous waiting logic so that it may be called from Objective-C and Swift. +internal class NMBWait: NSObject { +// About these kind of lines, `@objc` attributes are only required for Objective-C +// support, so that should be conditional on Darwin platforms and normal Xcode builds +// (non-SwiftPM builds). +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#else + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#endif + + // Using a throwable closure makes this method not objc compatible. + internal class func throwableUntil( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) throws -> Void) { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + // swiftlint:disable:next line_length + let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in + DispatchQueue.main.async { + let capture = NMBExceptionCapture( + handler: ({ exception in + done(.exception(exception)) + }), + finally: ({ }) + ) + capture.tryBlock { + do { + try action { + done(.none) + } + } catch let e { + done(.error(e)) + } + } + } + }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line) + + switch result { + case .incomplete: internalError("Reached .incomplete state for waitUntil(...).") + case .blockedRunLoop: + 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) + case let .raisedException(exception): + fail("Unexpected exception raised: \(exception)") + case let .errorThrown(error): + fail("Unexpected error thrown: \(error)") + case .completed(.exception(let exception)): + fail("Unexpected exception raised: \(exception)") + case .completed(.error(let error)): + fail("Unexpected error thrown: \(error)") + case .completed(.none): // success + break + } + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#else + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> 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." +} + +/// Wait asynchronously until the done closure is called or the timeout has been reached. +/// +/// @discussion +/// Call the done() closure to indicate the waiting has completed. +/// +/// 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) { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..e49bb0c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1,64 @@ +import Foundation + +/// Make an expectation on a given actual value. The value given is lazily evaluated. +public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { + 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: @escaping () throws -> T?) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Always fails the test with a message and a specified location. +public func fail(_ message: String, location: SourceLocation) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(false, message: FailureMessage(stringValue: message), location: location) +} + +/// Always fails the test with a message. +public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { + fail(message, location: SourceLocation(file: file, line: line)) +} + +/// Always fails the test. +public func fail(_ file: FileString = #file, line: UInt = #line) { + fail("fail() always fails", file: file, line: line) +} + +/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts +internal func nimblePrecondition( + _ expr: @autoclosure() -> Bool, + _ name: @autoclosure() -> String, + _ message: @autoclosure() -> String, + file: StaticString = #file, + line: UInt = #line) { + let result = expr() + if !result { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let e = NSException( + name: NSExceptionName(name()), + reason: message(), + userInfo: nil) + e.raise() +#else + preconditionFailure("\(name()) - \(message())", file: file, line: line) +#endif + } +} + +internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { + fatalError( + "Nimble Bug Found: \(msg) at \(file):\(line).\n" + + "Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " + + "code snippet that caused this error." + ) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..e3f616a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,132 @@ +import Foundation + +// Deprecated +internal func expressionMatches(_ expression: Expression, matcher: U, to: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let pass = try matcher.matches(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +// Deprecated +internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = toNot + do { + let pass = try matcher.doesNotMatch(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { + func run() -> (Bool, FailureMessage) { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let result = try predicate.satisfies(expression) + result.message.update(failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (result.toBoolean(expectation: style), msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } + } + + var result: (Bool, FailureMessage) = (false, FailureMessage()) + if captureExceptions { + let capture = NMBExceptionCapture(handler: ({ exception -> Void in + let msg = FailureMessage() + msg.stringValue = "unexpected exception raised: \(exception)" + result = (false, msg) + }), finally: nil) + capture.tryBlock { + result = run() + } + } else { + result = run() + } + + return result +} + +public struct Expectation { + + public let expression: Expression + + public func verify(_ pass: Bool, _ message: FailureMessage) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(pass, message: message, location: expression.location) + } + + ////////////////// OLD API ///////////////////// + + /// DEPRECATED: Tests the actual value using a matcher to match. + public func to(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionMatches(expression, matcher: matcher, to: "to", description: description) + verify(pass, msg) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + 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) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + toNot(matcher, description: description) + } + + ////////////////// NEW API ///////////////////// + + /// Tests the actual value using a matcher to match. + public func to(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ predicate: Predicate, description: String? = nil) { + toNot(predicate, description: description) + } + + // see: + // - AsyncMatcherWrapper for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift new file mode 100644 index 0000000..992ee0e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift @@ -0,0 +1,262 @@ +import Foundation + +public indirect enum ExpectationMessage { + // --- Primary Expectations --- + /// includes actual value in output ("expected to , got ") + case expectedActualValueTo(/* message: */ String) + /// uses a custom actual value string in output ("expected to , got ") + case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + /// excludes actual value in output ("expected to ") + case expectedTo(/* message: */ String) + /// allows any free-form message ("") + case fail(/* message: */ String) + + // --- Composite Expectations --- + // Generally, you'll want the methods, appended(message:) and appended(details:) instead. + + /// Not Fully Implemented Yet. + case prepends(/* Prepended Message */ String, ExpectationMessage) + + /// appends after an existing message (" (use beNil() to match nils)") + case appends(ExpectationMessage, /* Appended Message */ String) + + /// provides long-form multi-line explainations ("\n\n") + case details(ExpectationMessage, String) + + internal var sampleMessage: String { + let asStr = toString(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. + public var expectedMessage: String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return msg + case let .expectedActualValueTo(msg): + return msg + case let .expectedCustomValueTo(msg, _): + return msg + case let .prepends(_, expectation): + return expectation.expectedMessage + case let .appends(expectation, msg): + return "\(expectation.expectedMessage)\(msg)" + case let .details(expectation, _): + return expectation.expectedMessage + } + } + + /// Appends a message after the primary expectation message + public func appended(message: String) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo, .appends, .prepends: + return .appends(self, message) + case let .details(expectation, msg): + return .details(expectation.appended(message: message), msg) + } + } + + /// Appends a message hinting to use beNil() for when the actual value given was nil. + public func appendedBeNilHint() -> ExpectationMessage { + return appended(message: " (use beNil() to match nils)") + } + + /// Appends a detailed (aka - multiline) message after the primary expectation message + /// Detailed messages will be placed after .appended(message:) calls. + public func appended(details: String) -> ExpectationMessage { + return .details(self, details) + } + + internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(self) + case let .prepends(msg, expectation): + return .prepends(msg, expectation.visitLeafs(f)) + case let .appends(expectation, msg): + return .appends(expectation.visitLeafs(f), msg) + case let .details(expectation, msg): + return .details(expectation.visitLeafs(f), msg) + } + } + + /// Replaces a primary expectation with one returned by f. Preserves all composite expectations + /// that were built upon it (aka - all appended(message:) and appended(details:). + public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(msg) + default: + return msg + } + } + return visitLeafs(walk) + } + + /// Wraps a primary expectation with text before and after it. + /// Alias to prepended(message: before).appended(message: after) + public func wrappedExpectation(before: String, after: String) -> ExpectationMessage { + return prepended(expectation: before).appended(message: after) + } + + /// Prepends a message by modifying the primary expectation + public func prepended(expectation message: String) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case let .expectedTo(msg): + return .expectedTo(message + msg) + case let .expectedActualValueTo(msg): + return .expectedActualValueTo(message + msg) + case let .expectedCustomValueTo(msg, actual): + return .expectedCustomValueTo(message + msg, actual) + default: + return msg.visitLeafs(walk) + } + } + return visitLeafs(walk) + } + + // TODO: test & verify correct behavior + internal func prepended(message: String) -> ExpectationMessage { + return .prepends(message, self) + } + + /// Converts the tree of ExpectationMessages into a final built string. + public func toString(actual: String, expected: String = "expected", to: String = "to") -> String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return "\(expected) \(to) \(msg)" + case let .expectedActualValueTo(msg): + return "\(expected) \(to) \(msg), got \(actual)" + case let .expectedCustomValueTo(msg, actual): + return "\(expected) \(to) \(msg), got \(actual)" + case let .prepends(msg, expectation): + return "\(msg)\(expectation.toString(actual: actual, expected: expected, to: to))" + case let .appends(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\(msg)" + case let .details(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\n\n\(msg)" + } + } + + // Backwards compatibility: converts ExpectationMessage tree to FailureMessage + internal func update(failureMessage: FailureMessage) { + switch self { + case let .fail(msg): + failureMessage.stringValue = msg + case let .expectedTo(msg): + failureMessage.actualValue = nil + failureMessage.postfixMessage = msg + case let .expectedActualValueTo(msg): + failureMessage.postfixMessage = msg + case let .expectedCustomValueTo(msg, actual): + failureMessage.postfixMessage = msg + failureMessage.actualValue = actual + case let .prepends(msg, expectation): + expectation.update(failureMessage: failureMessage) + if let desc = failureMessage.userDescription { + failureMessage.userDescription = "\(msg)\(desc)" + } else { + failureMessage.userDescription = msg + } + case let .appends(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendMessage(msg) + case let .details(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendDetails(msg) + } + } +} + +extension FailureMessage { + internal func toExpectationMessage() -> ExpectationMessage { + let defaultMsg = FailureMessage() + if expected != defaultMsg.expected || _stringValueOverride != nil { + return .fail(stringValue) + } + + var msg: ExpectationMessage = .fail(userDescription ?? "") + if actualValue != "" && actualValue != nil { + msg = .expectedCustomValueTo(postfixMessage, actualValue ?? "") + } else if postfixMessage != defaultMsg.postfixMessage { + if actualValue == nil { + msg = .expectedTo(postfixMessage) + } else { + msg = .expectedActualValueTo(postfixMessage) + } + } + if postfixActual != defaultMsg.postfixActual { + msg = .appends(msg, postfixActual) + } + if let m = extendedMessage { + msg = .details(msg, m) + } + return msg + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +public class NMBExpectationMessage: NSObject { + private let msg: ExpectationMessage + + internal init(swift msg: ExpectationMessage) { + self.msg = msg + } + + public init(expectedTo message: String) { + self.msg = .expectedTo(message) + } + public init(expectedActualValueTo message: String) { + self.msg = .expectedActualValueTo(message) + } + + public init(expectedActualValueTo message: String, customActualValue actual: String) { + self.msg = .expectedCustomValueTo(message, actual) + } + + public init(fail message: String) { + self.msg = .fail(message) + } + + public init(prepend message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(appendedMessage message: String, child: NMBExpectationMessage) { + self.msg = .appends(child.msg, message) + } + + public init(prependedMessage message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(details message: String, child: NMBExpectationMessage) { + self.msg = .details(child.msg, message) + } + + public func appendedBeNilHint() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: msg.appendedBeNilHint()) + } + + public func toSwift() -> ExpectationMessage { return self.msg } +} + +extension ExpectationMessage { + func toObjectiveC() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..5a233fd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,99 @@ +import Foundation + +// Memoizes the given closure, only calling the passed +// closure once; even if repeat calls to the returned closure +internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { + var cache: T? + return ({ withoutCaching in + if withoutCaching || cache == nil { + cache = try closure() + } + return cache! + }) +} + +/// Expression represents the closure of the value inside expect(...). +/// Expressions are memoized by default. This makes them safe to call +/// evaluate() multiple times without causing a re-evaluation of the underlying +/// closure. +/// +/// @warning Since the closure can be any code, Objective-C code may choose +/// to raise an exception. Currently, Expression does not memoize +/// exception raising. +/// +/// This provides a common consumable API for matchers to utilize to allow +/// Nimble to change internals to how the captured closure is managed. +public struct Expression { + internal let _expression: (Bool) throws -> T? + internal let _withoutCaching: Bool + public let location: SourceLocation + public let isClosure: Bool + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. The expression is memoized. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { + self._expression = memoizedClosure(expression) + self.location = location + self._withoutCaching = false + self.isClosure = isClosure + } + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param withoutCaching Indicates if the struct should memoize the given + /// closure's result. Subsequent evaluate() calls will + /// not call the given closure if this is true. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { + self._expression = memoizedExpression + self.location = location + self._withoutCaching = withoutCaching + self.isClosure = isClosure + } + + /// Returns a new Expression from the given expression. Identical to a map() + /// on this type. This should be used only to typecast the Expression's + /// closure value. + /// + /// The returned expression will preserve location and isClosure. + /// + /// @param block The block that can cast the current Expression value to a + /// new type. + public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { + return Expression( + expression: ({ try block(self.evaluate()) }), + location: self.location, + isClosure: self.isClosure + ) + } + + public func evaluate() throws -> T? { + return try self._expression(_withoutCaching) + } + + public func withoutCaching() -> Expression { + return Expression( + memoizedExpression: self._expression, + location: location, + withoutCaching: true, + isClosure: isClosure + ) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..2bc57eb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,92 @@ +import Foundation + +/// Encapsulates the failure message that matchers can report to the end user. +/// +/// This is shared state between Nimble and matchers that mutate this value. +public class FailureMessage: NSObject { + public var expected: String = "expected" + public var actualValue: String? = "" // empty string -> use default; nil -> exclude + public var to: String = "to" + public var postfixMessage: String = "match" + public var postfixActual: String = "" + /// An optional message that will be appended as a new line and provides additional details + /// about the failure. This message will only be visible in the issue navigator / in logs but + /// not directly in the source editor since only a single line is presented there. + public var extendedMessage: String? + public var userDescription: String? + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + internal var hasOverriddenStringValue: Bool { + return _stringValueOverride != nil + } + + public override init() { + } + + public init(stringValue: String) { + _stringValueOverride = stringValue + } + + internal func stripNewlines(_ str: String) -> String { + let whitespaces = CharacterSet.whitespacesAndNewlines + return str + .components(separatedBy: "\n") + .map { line in line.trimmingCharacters(in: whitespaces) } + .joined(separator: "") + } + + internal func computeStringValue() -> String { + var value = "\(expected) \(to) \(postfixMessage)" + if let actualValue = actualValue { + value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" + } + value = stripNewlines(value) + + if let extendedMessage = extendedMessage { + value += "\n\(stripNewlines(extendedMessage))" + } + + if let userDescription = userDescription { + return "\(userDescription)\n\(value)" + } + + return value + } + + internal func appendMessage(_ msg: String) { + if hasOverriddenStringValue { + stringValue += "\(msg)" + } else if actualValue != nil { + postfixActual += msg + } else { + postfixMessage += msg + } + } + + internal func appendDetails(_ msg: String) { + if hasOverriddenStringValue { + if let desc = userDescription { + stringValue = "\(desc)\n\(stringValue)" + } + stringValue += "\n\(msg)" + } else { + if let desc = userDescription { + userDescription = desc + } + extendedMessage = msg + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 Jeff Hui. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..8affa62 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,121 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) throws -> Bool) -> Predicate + where U: Sequence, T == U.Iterator.Element { + let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in + return PredicateStatus(bool: try passFunc(try actualExpression.evaluate())) + } + return createPredicate(matcher) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate + 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(_ elementMatcher: M) -> Predicate + where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType { + return createPredicate(elementMatcher.predicate) +} + +public func allPass(_ elementPredicate: Predicate) -> Predicate + where S: Sequence { + return createPredicate(elementPredicate) +} + +private func createPredicate(_ elementMatcher: Predicate) -> Predicate + 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) + } + } + failure = failure.replacedExpectation({ expectation in + return .expectedTo(expectation.expectedMessage) + }) + return PredicateResult(status: .matches, message: failure) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate { + return NMBPredicate { actualExpression in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + var generator = NSFastEnumerationIterator(value) + while let obj = generator.next() { + if let nsObject = obj as? NSObject { + nsObjects.append(nsObject) + } else { + collectionIsUsable = false + break + } + } + } else { + collectionIsUsable = false + } + + if !collectionIsUsable { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + // swiftlint:disable:next line_length + fail: "allPass can only be used with types which implement NSFastEnumeration (NSArray, NSSet, ...), and whose elements subclass NSObject, got <\(actualValue?.description ?? "nil")>" + ) + ) + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in + if let predicate = matcher as? NMBPredicate { + return predicate.satisfies(({ try! expr.evaluate() }), location: expr.location).toSwift() + } else { + let failureMessage = FailureMessage() + let result = matcher.matches( + ({ try! expr.evaluate() }), + failureMessage: failureMessage, + location: expr.location + ) + let expectationMsg = failureMessage.toExpectationMessage() + return PredicateResult( + bool: result, + message: expectationMsg + ) + } + }) + return try! pred.satisfies(expr).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..3cba8b0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,236 @@ +import Foundation + +/// 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: TimeInterval = 1 + public static var PollInterval: TimeInterval = 0.01 +} + +private func async(style: ExpectationStyle, predicate: Predicate, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate { + return Predicate { actualExpression in + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).\(fnName)(...)" + var lastPredicateResult: PredicateResult? + let result = pollBlock( + pollInterval: poll, + timeoutInterval: timeout, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + lastPredicateResult = try predicate.satisfies(uncachedExpression) + return lastPredicateResult!.toBoolean(expectation: style) + } + switch result { + case .completed: return lastPredicateResult! + case .timedOut: return PredicateResult(status: .fail, message: lastPredicateResult!.message) + case let .errorThrown(error): + return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + case let .raisedException(exception): + return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) + case .blockedRunLoop: + // swiftlint:disable:next line_length + return PredicateResult(status: .fail, message: lastPredicateResult!.message.appended(message: " (timed out, but main thread was unresponsive).")) + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } +} + +// Deprecated +internal struct AsyncMatcherWrapper: Matcher + where U: Matcher, U.ValueType == T { + let fullMatcher: U + let timeoutInterval: TimeInterval + let pollInterval: TimeInterval + + init(fullMatcher: U, timeoutInterval: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval) { + self.fullMatcher = fullMatcher + self.timeoutInterval = timeoutInterval + self.pollInterval = pollInterval + } + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).toEventually(...)" + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + try self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: "expect(...).toEventuallyNot(...)") { + try self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventuallyNot(...).") + } + } +} + +private let toEventuallyRequiresClosureError = FailureMessage( + // swiftlint:disable:next line_length + stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function" +) + +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toMatch, + async(style: .toMatch, predicate: predicate, timeout: timeout, poll: pollInterval, fnName: "toEventually"), + to: "to eventually", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toNotMatch, + async( + style: .toNotMatch, + predicate: predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventuallyNot" + ), + to: "to eventually not", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + } +} + +// Deprecated +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionMatches( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + to: "to eventually", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionDoesNotMatch( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + toNot: "to eventually not", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..5674525 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,68 @@ +import Foundation + +private func matcherMessage(forType expectedType: T.Type) -> String { + return "be a kind of \(String(describing: expectedType))" +} +private func matcherMessage(forClass expectedClass: AnyClass) -> String { + return "be a kind of \(String(describing: expectedClass))" +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "") + return PredicateResult(status: .fail, message: message) + } + message = .expectedCustomValueTo( + "be a kind of \(String(describing: expectedType))", + "<\(String(describing: type(of: validInstance))) instance>" + ) + + return PredicateResult( + bool: validInstance is T, + message: message + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// 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 +public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + let status: PredicateStatus + + let instance = try actualExpression.evaluate() + if let validInstance = instance { + status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "<\(String(describing: type(of: validInstance))) instance>" + ) + } else { + status = .fail + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "" + ) + } + + return PredicateResult(status: status, message: message) + } +} + +extension NMBObjCMatcher { + @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAKindOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..70c5661 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,56 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. +public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedType))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + return PredicateResult( + status: .doesNotMatch, + message: .expectedActualValueTo(errorMessage) + ) + } + + let actualString = "<\(String(describing: type(of: validInstance))) instance>" + + return PredicateResult( + status: PredicateStatus(bool: type(of: validInstance) == expectedType), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAKindOf if you want to match against subclasses +public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedClass))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + let actualString: String + if let validInstance = instance { + actualString = "<\(String(describing: type(of: validInstance))) instance>" + } else { + actualString = "" + } + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let matches = instance != nil && instance!.isMember(of: expectedClass) + #else + let matches = instance != nil && type(of: instance!) == expectedClass + #endif + return PredicateResult( + status: PredicateStatus(bool: matches), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAnInstanceOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..34fa1b8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,126 @@ +import Foundation + +public let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, + expectedValue: NMBDoubleConvertible, + delta: Double) + -> PredicateResult { + let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + return PredicateResult( + bool: actualValue != nil && + abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta, + message: .expectedCustomValueTo(errorMessage, "<\(stringify(actualValue))>") + ) +} + +/// 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: Double, within delta: Double = DefaultDelta) -> Predicate { + 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 { + return Predicate.define { actualExpression in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + 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) + return try! matcher.matches(expr, failureMessage: failureMessage) + } + + @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) + return try! matcher.doesNotMatch(expr, failureMessage: failureMessage) + } + + @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) + } +} +#endif + +public func beCloseTo(_ expectedValues: [Double], within delta: Double = DefaultDelta) -> Predicate<[Double]> { + let errorMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + return Predicate.simple(errorMessage) { actualExpression in + if let actual = try actualExpression.evaluate() { + if actual.count != expectedValues.count { + return .doesNotMatch + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return .doesNotMatch + } + } + return .matches + } + } + return .doesNotMatch + } +} + +// MARK: - Operators + +infix operator ≈ : ComparisonPrecedence + +public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +public 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 +// unexpectantly +precedencegroup PlusMinusOperatorPrecedence { + higherThan: BitwiseShiftPrecedence +} + +infix operator ± : PlusMinusOperatorPrecedence +public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) { + return (expected: lhs, delta: rhs) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..3cbc15d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,95 @@ +import Foundation + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return .fail + } + var generator = actualSeq!.makeIterator() + return PredicateStatus(bool: generator.next() == nil) + } +} + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0) + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For NSString instances, it is an empty string. +public func beEmpty() -> Predicate { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || actualString!.length == 0) + } +} + +// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, +// etc, since they conform to Sequence as well as NMBCollection. + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualDictionary = try actualExpression.evaluate() + return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.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 { + return Predicate.simple("be empty") { actualExpression in + let actualArray = try actualExpression.evaluate() + return PredicateStatus(bool: actualArray == nil || actualArray!.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 { + return Predicate.simple("be empty") { actualExpression in + let actual = try actualExpression.evaluate() + return PredicateStatus(bool: actual == nil || actual!.count == 0) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @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) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let actualValue = actualValue { + // swiftlint:disable:next line_length + let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + expectedActualValueTo: badTypeErrorMsg, + customActualValue: "\(String(describing: type(of: actualValue))) type" + ) + ) + } + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() + ) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..8717f97 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil + && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending + return matches + }.requireNonNil +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..55d8e7b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -0,0 +1,44 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if let actual = actualValue, let expected = expectedValue { + return actual >= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..ad19def --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -0,0 +1,46 @@ +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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if os(Linux) + let actual = try actualExpression.evaluate() as? AnyObject + #else + let actual = try actualExpression.evaluate() as AnyObject? + #endif + failureMessage.actualValue = "\(identityAsString(actual))" + failureMessage.postfixMessage = "be identical to \(identityAsString(expected))" + #if os(Linux) + return actual === (expected as? AnyObject) && actual !== nil + #else + return actual === (expected as AnyObject?) && actual !== nil + #endif + }.requireNonNil +} + +public func === (lhs: Expectation, rhs: Any?) { + lhs.to(beIdenticalTo(rhs)) +} +public func !== (lhs: Expectation, rhs: Any?) { + lhs.toNot(beIdenticalTo(rhs)) +} + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +/// +/// Alias for "beIdenticalTo". +public func be(_ expected: Any?) -> Predicate { + return beIdenticalTo(expected) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let aExpr = actualExpression.cast { $0 as Any? } + return try! beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..8047efd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual < expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..f9e9f4e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual <= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + return actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedDescending + }.requireNonNil +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..2b18b4c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,167 @@ +import Foundation + +extension Int8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int8Value + } +} + +extension UInt8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint8Value + } +} + +extension Int16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int16Value + } +} + +extension UInt16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint16Value + } +} + +extension Int32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int32Value + } +} + +extension UInt32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint32Value + } +} + +extension Int64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int64Value + } +} + +extension UInt64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint64Value + } +} + +extension Float: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).floatValue + } +} + +extension Double: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).doubleValue + } +} + +extension Int: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).intValue + } +} + +extension UInt: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uintValue + } +} + +internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { + return Predicate { actualExpression in + let result = try matcher.satisfies(actualExpression) + return PredicateResult(status: result.status, message: message) + }.requireNonNil +} + +// MARK: beTrue() / beFalse() + +/// A Nimble matcher that succeeds when the actual value is exactly true. +/// This matcher will not match against nils. +public func beTrue() -> Predicate { + return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> Predicate { + return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> Predicate { + return Predicate.simpleNilable("be truthy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == true) + } + + return PredicateStatus(bool: actualValue == (true as T)) + } + return PredicateStatus(bool: actualValue != nil) + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> Predicate { + return Predicate.simpleNilable("be falsy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == false) + } + + return PredicateStatus(bool: actualValue == (false as T)) + } + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beTruthyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTruthy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalsyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalsy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beTrueMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTrue().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalseMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalse().matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..a22e0f4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,19 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> Predicate { + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..f5bf22a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift @@ -0,0 +1,18 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is Void. +public func beVoid() -> Predicate<()> { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be void" + let actualValue: ()? = try actualExpression.evaluate() + return actualValue != nil + } +} + +public func == (lhs: Expectation<()>, rhs: ()) { + lhs.to(beVoid()) +} + +public func != (lhs: Expectation<()>, rhs: ()) { + lhs.toNot(beVoid()) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..c2ab568 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,60 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's first element +/// is equal to the expected value. +public func beginWith(_ startingElement: T) -> Predicate + where S.Iterator.Element == T { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> Predicate { + return Predicate.simple("begin with <\(startingElement)>") { actualExpression in + guard let collection = try actualExpression.evaluate() else { return .fail } + guard collection.count > 0 else { return .doesNotMatch } + #if os(Linux) + guard let collectionValue = collection.object(at: 0) as? NSObject else { + return .fail + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return PredicateStatus(bool: collectionValue.isEqual(startingElement)) + } +} + +/// A Nimble matcher that succeeds when the actual string contains expected substring +/// where the expected substring's location is zero. +public func beginWith(_ startingSubstring: String) -> Predicate { + return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return PredicateStatus(bool: range != nil && range!.lowerBound == actual.startIndex) + } + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! beginWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..f1afb72 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,95 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> Predicate + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + if let actual = try actualExpression.evaluate() { + return items.all { + return actual.contains($0) + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { + let range = actual.range(of: $0) + return range != nil && !range!.isEmpty + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { actual.range(of: $0.description).length != 0 } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> Predicate { + return contain(items) +} + +public func contain(_ items: [Any?]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + guard let actual = try actualExpression.evaluate() else { return false } + return items.all { item in + return item != nil && actual.contains(item!) + } + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + if let value = actualValue as? NMBContainer { + let expr = Expression(expression: ({ value as NMBContainer }), location: location) + + // A straightforward cast on the array causes this to crash, so we have to cast the individual items + let expectedOptionals: [Any?] = expected.map({ $0 as Any? }) + return try! contain(expectedOptionals).matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! contain(expected as! [String]).matches(expr, failureMessage: failureMessage) + } else if actualValue != nil { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)" + } else { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..ae0d854 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,60 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T { + + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.actualValue = nil + + if predicateDescription == "" { + failureMessage.postfixMessage = "find object in collection that satisfies predicate" + } else { + failureMessage.postfixMessage = "find object in collection \(predicateDescription)" + } + + if let sequence = try actualExpression.evaluate() { + for object in sequence { + if predicate(object) { + return true + } + } + + return false + } + + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + extension NMBObjCMatcher { + @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let value = try! actualExpression.evaluate() + guard let enumeration = value as? NSFastEnumeration else { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + var iterator = NSFastEnumerationIterator(enumeration) + while let item = iterator.next() { + guard let object = item as? NSObject else { + continue + } + + if predicate(object) { + return true + } + } + + failureMessage.actualValue = nil + failureMessage.postfixMessage = "" + failureMessage.to = "to find object in collection that satisfies predicate" + return false + } + } + } +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..a6f9f91 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift @@ -0,0 +1,72 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's last element +/// is equal to the expected value. +public func endWith(_ endingElement: T) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + + 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) + + return lastItem == endingElement + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + guard let collection = try actualExpression.evaluate() else { return false } + guard collection.count > 0 else { return false } + #if os(Linux) + guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: collection.count - 1) as AnyObject + #endif + + return collectionValue.isEqual(endingElement) + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring +/// where the expected substring's location is the actual string's length minus the +/// expected substring's length. +public func endWith(_ endingSubstring: String) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingSubstring)>" + if let collection = try actualExpression.evaluate() { + return collection.hasSuffix(endingSubstring) + } + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! endWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! endWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..9467154 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,220 @@ +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. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(status: PredicateStatus(bool: matches), message: msg) + } +} + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: [T: C]?) -> Predicate<[T: C]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult( + status: PredicateStatus(bool: expectedValue! == actualValue!), + message: msg + ) + } +} + +/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection. +/// Items must implement the Equatable protocol. +public func equal(_ expectedValue: [T]?) -> Predicate<[T]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult( + status: .fail, + message: msg + ) + } + return PredicateResult( + bool: expectedValue! == actualValue!, + message: msg + ) + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + if let actualValue = try actualExpression.evaluate() { + let doesNotMatch = PredicateResult( + status: .doesNotMatch, + message: msg + ) + + if expectedValue.count != actualValue.count { + return doesNotMatch + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return doesNotMatch + } else if item != nil && otherItem == nil { + return doesNotMatch + } else if item! != otherItem! { + return doesNotMatch + } + } + + return PredicateResult( + status: .matches, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { stringify($0) }) +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { + if let set = $0 { + return stringify(Array(set).sorted { $0 < $1 }) + } else { + return "nil" + } + }) +} + +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { + return Predicate { actualExpression in + var errorMessage: ExpectationMessage = + .expectedActualValueTo("equal <\(stringify(expectedValue))>") + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + errorMessage = .expectedCustomValueTo( + "equal <\(stringify(expectedValue))>", + "<\(stringify(actualValue))>" + ) + + if expectedValue == actualValue { + return PredicateResult( + status: .matches, + message: errorMessage + ) + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>") + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") + } + return PredicateResult( + status: .doesNotMatch, + message: errorMessage + ) + } + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } else { + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } + } +} + +public func ==(lhs: Expectation, rhs: T?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation, rhs: T?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.toNot(equal(rhs)) +} + +public func == (lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func != (lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.toNot(equal(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! equal(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..93335a8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,59 @@ +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. +// The representation of the collection content is provided in a new line as an `extendedMessage`. + +/// A Nimble matcher that succeeds when the actual Collection's count equals +/// the expected value +public func haveCount(_ expectedValue: T.IndexDistance) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage 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) + return try! haveCount(expected.intValue).matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable" + failureMessage.actualValue = "\(String(describing: type(of: actualValue)))" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..1e5762f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift @@ -0,0 +1,30 @@ +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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "match <\(stringify(expectedValue))>" + + if let actual = try actualExpression.evaluate() { + if let regexp = expectedValue { + return actual.range(of: regexp, options: .regularExpression) != nil + } + } + + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +extension NMBObjCMatcher { + @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.cast { $0 as? String } + return try! match(expected.description).matches(actual, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..9c86fb7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,58 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + errorType: errorType + ) + var matches = false + if actualError as? T != nil { + matches = true + } + return matches + }.requireNonNil +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..abcafa9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,85 @@ +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil +/// values are received in an expectation. +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct MatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try matcher(actualExpression, failureMessage) + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try !matcher(actualExpression, failureMessage) + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} + +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// Unlike MatcherFunc, this will always fail if an expectation contains nil. +/// This applies regardless of using to() or toNot(). +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct NonNilMatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try !matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return true + } + return false + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..6f8f103 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,154 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +@available(*, deprecated, message: "Use Predicate instead") +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +extension Matcher { + var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } + + var toClosure: (Expression, FailureMessage, Bool) throws -> Bool { + return ({ expr, msg, expectedResult in + if expectedResult { + return try self.matches(expr, failureMessage: msg) + } else { + return try self.doesNotMatch(expr, failureMessage: msg) + } + }) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +/// Objective-C interface to the Swift variant of Matcher. +@objc public protocol NMBMatcher { + func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool + func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool +} +#endif + +/// Protocol for types that support contain() matcher. +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a +//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet +#endif + +extension NSArray: NMBContainer {} +extension NSSet: NMBContainer {} + +/// Protocol for types that support only beEmpty(), haveCount() matchers +public protocol NMBCollection { + var count: Int { get } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable: NMBCollection {} +#endif + +extension NSSet: NMBCollection {} +extension NSIndexSet: NMBCollection {} +extension NSDictionary: NMBCollection {} + +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} + +extension NSArray: NMBOrderedCollection {} + +public protocol NMBDoubleConvertible { + var doubleValue: CDouble { get } +} + +extension Double: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self + } +} + +extension Float: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension CGFloat: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension NSNumber: NMBDoubleConvertible { +} + +private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.locale = Locale(identifier: "en_US_POSIX") + + return formatter +}() + +extension Date: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension NSDate: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension Date: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: self) + } +} + +extension NSDate: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) + } +} + +/// 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 os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@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 { + return compare(otherObject as! NSNumber) + } +} +extension NSString: NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! String) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..ee886f1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,96 @@ +import Foundation + +// A workaround to SR-6419. +extension NotificationCenter { +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + #if swift(>=4.0) + #if swift(>=4.0.2) + #else + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #elseif swift(>=3.2) + #if swift(>=3.2.2) + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif +#endif +} + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + // swiftlint:disable:next line_length + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil, using: { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + }) + } + + deinit { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + if let token = self.token { + self.notificationCenter.removeObserver(token) + } + #else + if let token = self.token as? AnyObject { + self.notificationCenter.removeObserver(token) + } + #endif + } +} + +private let mainThread = pthread_self() + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = .default) + -> Predicate + where T: Matcher, T.ValueType == [Notification] +{ + _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + collector.startObserving() + var once: Bool = false + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage 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 match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) + if collector.observedNotifications.isEmpty { + failureMessage.actualValue = "no notifications" + } else { + failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" + } + return match + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift new file mode 100644 index 0000000..f812344 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift @@ -0,0 +1,348 @@ +// New Matcher API +// +import Foundation + +/// A Predicate is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate +/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble +/// matcher API. +/// +/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, +/// predicates are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +public struct Predicate { + fileprivate var matcher: (Expression) throws -> PredicateResult + + /// Constructs a predicate that knows how take a given value + public init(_ matcher: @escaping (Expression) throws -> PredicateResult) { + self.matcher = matcher + } + + /// Uses a predicate on a given value to see if it passes the predicate. + /// + /// @param expression The value to run the predicate's logic against + /// @returns A predicate result indicate passing or failing and an associated error message. + public func satisfies(_ expression: Expression) throws -> PredicateResult { + return try matcher(expression) + } +} + +/// Provides convenience helpers to defining predicates +extension Predicate { + /// Like Predicate() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (Expression) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual) + }.requireNonNil + } + + /// 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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + }.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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + } + } +} + +extension Predicate { + /// Provides a simple predicate definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the predicate's actual value cannot pass with `nil` given. + public static func simple(_ msg: String, matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + }.requireNonNil + } + + /// Provides a simple predicate definition that provides no control over the predefined + /// 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) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + } + } +} + +// The Expectation style intended for comparison to a PredicateStatus. +public enum ExpectationStyle { + case toMatch, toNotMatch +} + +/// The value that a Predicates return to describe if the given (actual) value matches the +/// predicate. +public struct PredicateResult { + /// Status indicates if the predicate matches, does not match, or fails. + public var status: PredicateStatus + /// The error message that can be displayed if it does not match + public var message: ExpectationMessage + + /// Constructs a new PredicateResult with a given status and error message + public init(status: PredicateStatus, message: ExpectationMessage) { + self.status = status + self.message = message + } + + /// Shorthand to PredicateResult(status: PredicateStatus(bool: bool), message: message) + public init(bool: Bool, message: ExpectationMessage) { + self.status = PredicateStatus(bool: bool) + self.message = message + } + + /// Converts the result to a boolean based on what the expectation intended + public func toBoolean(expectation style: ExpectationStyle) -> Bool { + return status.toBoolean(expectation: style) + } +} + +/// PredicateStatus is a trinary that indicates if a Predicate matches a given value or not +public enum PredicateStatus { + /// Matches indicates if the predicate / matcher passes with the given value + /// + /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. + case matches + /// DoesNotMatch indicates if the predicate / matcher fails with the given value, but *would* + /// succeed if the expectation was inverted. + /// + /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. + case doesNotMatch + /// Fail indicates the predicate will never satisfy with the given value in any case. + /// A perfect example is that most matchers fail whenever given `nil`. + /// + /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. + /// Note: Predicate's `requireNonNil` property will also provide this feature mostly for free. + /// Your predicate will still need to guard against nils, but error messaging will be + /// handled for you. + case fail + + /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). + public init(bool matches: Bool) { + if matches { + self = .matches + } else { + self = .doesNotMatch + } + } + + private func shouldMatch() -> Bool { + switch self { + case .matches: return true + case .doesNotMatch, .fail: return false + } + } + + private func shouldNotMatch() -> Bool { + switch self { + case .doesNotMatch: return true + case .matches, .fail: return false + } + } + + /// Converts the PredicateStatus result to a boolean based on what the expectation intended + internal func toBoolean(expectation style: ExpectationStyle) -> Bool { + if style == .toMatch { + return shouldMatch() + } else { + return shouldNotMatch() + } + } +} + +// Backwards compatibility until Old Matcher API removal +extension Predicate: Matcher { + /// Compatibility layer for old Matcher API, deprecated + public static func fromDeprecatedFullClosure(_ matcher: @escaping (Expression, FailureMessage, Bool) throws -> Bool) -> Predicate { + return Predicate { actual in + let failureMessage = FailureMessage() + let result = try matcher(actual, failureMessage, true) + return PredicateResult( + status: PredicateStatus(bool: result), + message: failureMessage.toExpectationMessage() + ) + } + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Emulates the MatcherFunc API + public static func fromDeprecatedClosure(_ matcher: @escaping (Expression, 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() + ) + } + + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Same as calling .predicate on a MatcherFunc or NonNilMatcherFunc type. + public static func fromDeprecatedMatcher(_ matcher: M) -> Predicate where M: Matcher, M.ValueType == T { + return self.fromDeprecatedFullClosure(matcher.toClosure) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toMatch) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toNotMatch) + } +} + +extension Predicate { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (Expression, PredicateResult) throws -> PredicateResult) -> Predicate { + return Predicate { actual -> PredicateResult in + let result = try self.satisfies(actual) + return try f(actual, result) + } + } + + /// Returns a new Predicate based on the current one that always fails if nil is given as + /// the actual value. + /// + /// This replaces `NonNilMatcherFunc`. + public var requireNonNil: Predicate { + return after { actual, result in + if try actual.evaluate() == nil { + return PredicateResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public typealias PredicateBlock = (_ actualExpression: Expression) -> NMBPredicateResult + +public class NMBPredicate: NSObject { + private let predicate: PredicateBlock + + public init(predicate: @escaping PredicateBlock) { + self.predicate = predicate + } + + func satisfies(_ expression: @escaping () -> NSObject?, location: SourceLocation) -> NMBPredicateResult { + let expr = Expression(expression: expression, location: location) + return self.predicate(expr) + } +} + +extension NMBPredicate: NMBMatcher { + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toMatch) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toNotMatch) + } +} + +final public class NMBPredicateResult: NSObject { + public var status: NMBPredicateStatus + public var message: NMBExpectationMessage + + public init(status: NMBPredicateStatus, message: NMBExpectationMessage) { + self.status = status + self.message = message + } + + public init(bool success: Bool, message: NMBExpectationMessage) { + self.status = NMBPredicateStatus.from(bool: success) + self.message = message + } + + public func toSwift() -> PredicateResult { + return PredicateResult(status: status.toSwift(), + message: message.toSwift()) + } +} + +extension PredicateResult { + public func toObjectiveC() -> NMBPredicateResult { + return NMBPredicateResult(status: status.toObjectiveC(), message: message.toObjectiveC()) + } +} + +final public class NMBPredicateStatus: NSObject { + private let status: Int + private init(status: Int) { + self.status = status + } + + public static let matches: NMBPredicateStatus = NMBPredicateStatus(status: 0) + public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1) + public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2) + + public override var hashValue: Int { return self.status.hashValue } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherPredicate = object as? NMBPredicateStatus else { + return false + } + return self.status == otherPredicate.status + } + + public static func from(status: PredicateStatus) -> NMBPredicateStatus { + switch status { + case .matches: return self.matches + case .doesNotMatch: return self.doesNotMatch + case .fail: return self.fail + } + } + + public static func from(bool success: Bool) -> NMBPredicateStatus { + return self.from(status: PredicateStatus(bool: success)) + } + + public func toSwift() -> PredicateStatus { + switch status { + case NMBPredicateStatus.matches.status: return .matches + case NMBPredicateStatus.doesNotMatch.status: return .doesNotMatch + case NMBPredicateStatus.fail.status: return .fail + default: + internalError("Unhandle status for NMBPredicateStatus") + } + } +} + +extension PredicateStatus { + public func toObjectiveC() -> NMBPredicateStatus { + return NMBPredicateStatus.from(status: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..3e7f2df --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,198 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +/// 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( + named: String? = nil, + reason: String? = nil, + userInfo: NSDictionary? = nil, + closure: ((NSException) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var exception: NSException? + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + _ = try! actualExpression.evaluate() + return + } + + setFailureMessageForException( + failureMessage, + exception: exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + return exceptionMatchesNonNilFieldsOrClosure( + exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + } +} + +// swiftlint:disable:next function_parameter_count +internal func setFailureMessageForException( + _ failureMessage: FailureMessage, + exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) { + failureMessage.postfixMessage = "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 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" + } +} + +internal func exceptionMatchesNonNilFieldsOrClosure( + _ exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) -> Bool { + var matches = false + + if let exception = exception { + matches = true + + if let named = named, exception.name.rawValue != named { + matches = false + } + if reason != nil && exception.reason != reason { + matches = false + } + if let userInfo = userInfo, let exceptionUserInfo = exception.userInfo, + (exceptionUserInfo as NSDictionary) != userInfo { + matches = false + } + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(exception) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} + +public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher { + internal var _name: String? + internal var _reason: String? + internal var _userInfo: NSDictionary? + internal var _block: ((NSException) -> Void)? + + internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) { + _name = name + _reason = reason + _userInfo = userInfo + _block = block + } + + @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) + + return try! raiseException( + named: _name, + reason: _reason, + userInfo: _userInfo, + closure: _block + ).matches(expr, failureMessage: failureMessage) + } + + @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( + 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 + ) + }) + } +} + +extension NMBObjCMatcher { + @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift new file mode 100644 index 0000000..6c63a15 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift @@ -0,0 +1,101 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAllOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAllOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = true + for matcher in matchers { + if try matcher.doesNotMatch(actualExpression, failureMessage: failureMessage) { + matches = false + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match all of: " + postfixMessages.componentsJoined(by: ", and ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = true + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toNotMatch) { + matches = false + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match all of: " + postfixMessages.joined(separator: ", and "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match all of: " + postfixMessages.joined(separator: ", and ") + ) + } + + return PredicateResult( + bool: matches, + message: msg + ) + }.requireNonNil +} + +public func && (left: Predicate, right: Predicate) -> Predicate { + return satisfyAllOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAllOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..d02a0ff --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,109 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAnyOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = false + for matcher in matchers { + if try matcher.matches(actualExpression, failureMessage: failureMessage) { + matches = true + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match one of: " + postfixMessages.componentsJoined(by: ", or ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = false + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toMatch) { + matches = true + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match one of: " + postfixMessages.joined(separator: ", or "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match one of: " + postfixMessages.joined(separator: ", or ") + ) + } + + return PredicateResult( + status: PredicateStatus(bool: matches), + message: msg + ) + }.requireNonNil +} + +public func || (left: Predicate, right: Predicate) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAnyOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..a530c60 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,56 @@ +import Foundation + +public func throwAssertion() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if arch(x86_64) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + failureMessage.postfixMessage = "throw an assertion" + failureMessage.actualValue = nil + + var succeeded = true + + let caughtException: BadInstructionException? = catchBadInstruction { + #if os(tvOS) + if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { + print() + print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + + "fatal error while using throwAssertion(), please disable 'Debug Executable' " + + "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + + "'Debug Executable'. If you've already done that, suppress this warning " + + "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + + "This is required because the standard methods of catching assertions " + + "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + + "debugger uses is the fallback method for tvOS." + ) + print() + NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true + } + #endif + do { + try actualExpression.evaluate() + } catch let error { + succeeded = false + failureMessage.postfixMessage += "; threw error instead <\(error)>" + } + } + + if !succeeded { + return false + } + + if caughtException == nil { + return false + } + + return true + #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. Mac, iPhone 5s or later simulators). You can silence this error " + + "by placing the test case inside an #if arch(x86_64) or (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) conditional statement") + // swiftlint:disable:previous line_length + #endif + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..872ca5c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,258 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + failureMessage.postfixMessage = "throw any error" + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } + return actualError != nil + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError( + errorType: T.Type, + closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: nil, + errorType: errorType, + closure: closure + ) + var matches = false + if let actualError = actualError { + matches = true + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } else { + matches = (actualError is T) + // The closure expects another ErrorProtocol as argument, so this + // is _supposed_ to fail, so that it becomes more obvious. + if let closure = closure { + let assertions = gatherExpectations { + if let actual = actualError as? T { + closure(actual) + } + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + } + + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// 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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// values of the existential type `Error` in the closure. +/// +/// The closure only gets called when an error was thrown. +public func throwError(closure: @escaping ((T) -> Void)) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError as? T { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift new file mode 100644 index 0000000..01369bb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift @@ -0,0 +1,37 @@ +/** + Used by the `toSucceed` matcher. + + This is the return type for the closure. + */ +public enum ToSucceedResult { + case succeeded + case failed(reason: String) +} + +/** + A Nimble matcher that takes in a closure for validation. + + Return `.succeeded` when the validation succeeds. + Return `.failed` with a failure reason when the validation fails. + */ +public func succeed() -> Predicate<() -> ToSucceedResult> { + return Predicate.define { actualExpression in + let optActual = try actualExpression.evaluate() + guard let actual = optActual else { + return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) + } + + switch actual() { + case .succeeded: + return PredicateResult( + bool: true, + message: .expectedCustomValueTo("succeed", "") + ) + case .failed(let reason): + return PredicateResult( + bool: false, + message: .expectedCustomValueTo("succeed", " because <\(reason)>") + ) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..2bbc693 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,13 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#if TARGET_OS_TV + #import "CwlPreconditionTesting_POSIX.h" +#else + #import "CwlPreconditionTesting.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..c77a8fc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,377 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + import CDispatch +#endif + +private let timeoutLeeway = DispatchTimeInterval.milliseconds(1) +private let pollLeeway = DispatchTimeInterval.milliseconds(1) + +/// Stores debugging information about callers +internal struct WaitingInfo: CustomStringConvertible { + let name: String + let file: FileString + let lineNumber: UInt + + var description: String { + return "\(name) at \(file):\(lineNumber)" + } +} + +internal protocol WaitLock { + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) + func releaseWaitingLock() + func isWaitingLocked() -> Bool +} + +internal class AssertionWaitLock: WaitLock { + private var currentWaiter: WaitingInfo? + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let isMainThread = Thread.isMainThread + #else + let isMainThread = _CFIsMainThread() + #endif + nimblePrecondition( + isMainThread, + "InvalidNimbleAPIUsage", + "\(fnName) can only run on the main thread." + ) + nimblePrecondition( + currentWaiter == nil, + "InvalidNimbleAPIUsage", + "Nested async expectations are not allowed to avoid creating flaky tests.\n\n" + + "The call to\n\t\(info)\n" + + "triggered this exception because\n\t\(currentWaiter!)\n" + + "is currently managing the main run loop." + ) + currentWaiter = info + } + + func isWaitingLocked() -> Bool { + return currentWaiter != nil + } + + func releaseWaitingLock() { + currentWaiter = nil + } +} + +internal enum AwaitResult { + /// Incomplete indicates None (aka - this value hasn't been fulfilled yet) + case incomplete + /// TimedOut indicates the result reached its defined timeout limit before returning + case timedOut + /// BlockedRunLoop indicates the main runloop is too busy processing other blocks to trigger + /// the timeout code. + /// + /// This may also mean the async code waiting upon may have never actually ran within the + /// required time because other timers & sources are running on the main run loop. + case blockedRunLoop + /// The async block successfully executed and returned a given result + case completed(T) + /// When a Swift Error is thrown + case errorThrown(Error) + /// When an Objective-C Exception is raised + case raisedException(NSException) + + func isIncomplete() -> Bool { + switch self { + case .incomplete: return true + default: return false + } + } + + func isCompleted() -> Bool { + switch self { + case .completed: return true + default: return false + } + } +} + +/// Holds the resulting value from an asynchronous expectation. +/// This class is thread-safe at receiving an "response" to this promise. +internal class AwaitPromise { + private(set) internal var asyncResult: AwaitResult = .incomplete + private var signal: DispatchSemaphore + + init() { + signal = DispatchSemaphore(value: 1) + } + + deinit { + signal.signal() + } + + /// Resolves the promise with the given result if it has not been resolved. Repeated calls to + /// this method will resolve in a no-op. + /// + /// @returns a Bool that indicates if the async result was accepted or rejected because another + /// value was received first. + func resolveResult(_ result: AwaitResult) -> Bool { + if signal.wait(timeout: .now()) == .success { + self.asyncResult = result + return true + } else { + return false + } + } +} + +internal struct AwaitTrigger { + let timeoutSource: DispatchSourceTimer + let actionSource: DispatchSourceTimer? + let start: () throws -> Void +} + +/// Factory for building fully configured AwaitPromises and waiting for their results. +/// +/// This factory stores all the state for an async expectation so that Await doesn't +/// doesn't have to manage it. +internal class AwaitPromiseBuilder { + let awaiter: Awaiter + let waitLock: WaitLock + let trigger: AwaitTrigger + let promise: AwaitPromise + + internal init( + awaiter: Awaiter, + waitLock: WaitLock, + promise: AwaitPromise, + trigger: AwaitTrigger) { + self.awaiter = awaiter + self.waitLock = waitLock + self.promise = promise + self.trigger = trigger + } + + func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + // = Discussion = + // + // There's a lot of technical decisions here that is useful to elaborate on. This is + // definitely more lower-level than the previous NSRunLoop based implementation. + // + // + // Why Dispatch Source? + // + // + // We're using a dispatch source to have better control of the run loop behavior. + // A timer source gives us deferred-timing control without having to rely as much on + // a run loop's traditional dispatching machinery (eg - NSTimers, DefaultRunLoopMode, etc.) + // which is ripe for getting corrupted by application code. + // + // And unlike dispatch_async(), we can control how likely our code gets prioritized to + // executed (see leeway parameter) + DISPATCH_TIMER_STRICT. + // + // This timer is assumed to run on the HIGH priority queue to ensure it maintains the + // highest priority over normal application / test code when possible. + // + // + // Run Loop Management + // + // In order to properly interrupt the waiting behavior performed by this factory class, + // this timer stops the main run loop to tell the waiter code that the result should be + // checked. + // + // In addition, stopping the run loop is used to halt code executed on the main run loop. + #if swift(>=4.0) + trigger.timeoutSource.schedule( + deadline: DispatchTime.now() + timeoutInterval, + repeating: .never, + leeway: timeoutLeeway + ) + #else + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway + ) + #endif + trigger.timeoutSource.setEventHandler { + guard self.promise.asyncResult.isIncomplete() else { return } + let timedOutSem = DispatchSemaphore(value: 0) + let semTimedOutOrBlocked = DispatchSemaphore(value: 0) + semTimedOutOrBlocked.signal() + let runLoop = CFRunLoopGetMain() + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + let now = DispatchTime.now() + forcefullyAbortTimeout + let didNotTimeOut = timedOutSem.wait(timeout: now) != .success + let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success + if didNotTimeOut && timeoutWasNotTriggered { + if self.promise.resolveResult(.blockedRunLoop) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + return self + } + + /// Blocks for an asynchronous result. + /// + /// @discussion + /// This function must be executed on the main thread and cannot be nested. This is because + /// this function (and it's related methods) coordinate through the main run loop. Tampering + /// with the run loop can cause undesirable behavior. + /// + /// This method will return an AwaitResult in the following cases: + /// + /// - The main run loop is blocked by other operations and the async expectation cannot be + /// be stopped. + /// - The async expectation timed out + /// - The async expectation succeeded + /// - The async expectation raised an unexpected exception (objc) + /// - The async expectation raised an unexpected error (swift) + /// + /// The returned AwaitResult will NEVER be .incomplete. + func wait(_ fnName: String = #function, file: FileString = #file, line: UInt = #line) -> AwaitResult { + waitLock.acquireWaitingLock( + fnName, + file: file, + line: line) + + let capture = NMBExceptionCapture(handler: ({ exception in + _ = self.promise.resolveResult(.raisedException(exception)) + }), finally: ({ + self.waitLock.releaseWaitingLock() + })) + capture.tryBlock { + do { + try self.trigger.start() + } catch let error { + _ = self.promise.resolveResult(.errorThrown(error)) + } + self.trigger.timeoutSource.resume() + while self.promise.asyncResult.isIncomplete() { + // Stopping the run loop does not work unless we run only 1 mode + _ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture) + } + + self.trigger.timeoutSource.cancel() + if let asyncSource = self.trigger.actionSource { + asyncSource.cancel() + } + } + + return promise.asyncResult + } +} + +internal class Awaiter { + let waitLock: WaitLock + let timeoutQueue: DispatchQueue + let asyncQueue: DispatchQueue + + internal init( + waitLock: WaitLock, + asyncQueue: DispatchQueue, + timeoutQueue: DispatchQueue) { + self.waitLock = waitLock + self.asyncQueue = asyncQueue + self.timeoutQueue = timeoutQueue + } + + private func createTimerSource(_ queue: DispatchQueue) -> DispatchSourceTimer { + return DispatchSource.makeTimerSource(flags: .strict, queue: queue) + } + + func performBlock( + file: FileString, + line: UInt, + _ closure: @escaping (@escaping (T) -> Void) throws -> Void + ) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + var completionCount = 0 + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) { + try closure { + completionCount += 1 + if completionCount < 2 { + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } else { + fail("waitUntil(..) expects its completion closure to be only called once", + file: file, line: line) + } + } + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } + + func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + 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))) + #if swift(>=4.0) + asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway) + #else + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + #endif + asyncSource.setEventHandler { + do { + if let result = try closure() { + if promise.resolveResult(.completed(result)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } catch let error { + if promise.resolveResult(.errorThrown(error)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } + asyncSource.resume() + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } +} + +internal func pollBlock( + pollInterval: TimeInterval, + timeoutInterval: TimeInterval, + file: FileString, + line: UInt, + fnName: String = #function, + expression: @escaping () throws -> Bool) -> AwaitResult { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let result = awaiter.poll(pollInterval) { () throws -> Bool? in + if try expression() { + return true + } + return nil + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..074cb20 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,59 @@ +import Foundation + +// Generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + postfixMessageVerb: String = "throw", + actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) { + failureMessage.postfixMessage = "\(postfixMessageVerb) error" + + if let error = error { + failureMessage.postfixMessage += " <\(error)>" + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } + if error == nil && errorType == nil && closure == nil { + failureMessage.postfixMessage = "\(postfixMessageVerb) any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool { + return actualError._domain == expectedError._domain + && actualError._code == expectedError._code +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift @@ -0,0 +1,12 @@ +import Foundation + +extension Sequence { + internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool { + for item in self { + if !fn(item) { + return false + } + } + return true + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift @@ -0,0 +1,31 @@ +import Foundation + +// Ideally we would always use `StaticString` as the type for tracking the file name +// that expectations originate from, for consistency with `assert` etc. from the +// stdlib, and because recent versions of the XCTest overlay require `StaticString` +// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we +// have to use `String` instead because StaticString can't be generated from Objective-C +#if SWIFT_PACKAGE +public typealias FileString = StaticString +#else +public typealias FileString = String +#endif + +public final class SourceLocation: NSObject { + public let file: FileString + public let line: UInt + + override init() { + file = "Unknown File" + line = 0 + } + + init(file: FileString, line: UInt) { + self.file = file + self.line = line + } + + override public var description: String { + return "\(file):\(line)" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..7c4d273 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift @@ -0,0 +1,206 @@ +import Foundation + +internal func identityAsString(_ value: Any?) -> String { + let anyObject: AnyObject? +#if os(Linux) + anyObject = value as? AnyObject +#else + anyObject = value as AnyObject? +#endif + if let value = anyObject { + return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description + } else { + return "nil" + } +} + +internal func arrayAsString(_ items: [T], joiner: String = ", ") -> String { + return items.reduce("") { accum, item in + let prefix = (accum.isEmpty ? "" : joiner) + return accum + prefix + "\(stringify(item))" + } +} + +/// A type with a customized test output text representation. +/// +/// This textual representation is produced when values will be +/// printed in test runs, and may be useful when producing +/// error messages in custom matchers. +/// +/// - SeeAlso: `CustomDebugStringConvertible` +public protocol TestOutputStringConvertible { + var testDescription: String { get } +} + +extension Double: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension Float: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +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 { + case 1: + return NSString(format: "%0.1f", self.doubleValue).description + case 2: + return NSString(format: "%0.2f", self.doubleValue).description + case 3: + return NSString(format: "%0.3f", self.doubleValue).description + default: + return NSString(format: "%0.4f", self.doubleValue).description + } + } + return self.description + } +} + +extension Array: TestOutputStringConvertible { + public var testDescription: String { + let list = self.map(Nimble.stringify).joined(separator: ", ") + return "[\(list)]" + } +} + +extension AnySequence: TestOutputStringConvertible { + public var testDescription: String { + let generator = self.makeIterator() + var strings = [String]() + var value: AnySequence.Iterator.Element? + + repeat { + value = generator.next() + if let value = value { + strings.append(stringify(value)) + } + } while value != nil + + let list = strings.joined(separator: ", ") + return "[\(list)]" + } +} + +extension NSArray: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension NSIndexSet: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension String: TestOutputStringConvertible { + public var testDescription: String { + return self + } +} + +extension Data: TestOutputStringConvertible { + public var testDescription: String { + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16) + return "Data" + #else + return "Data" + #endif + } +} + +/// +/// Returns a string appropriate for displaying in test output +/// from the provided value. +/// +/// - parameter value: A value that will show up in a test's output. +/// +/// - returns: The string that is returned can be +/// customized per type by conforming a type to the `TestOutputStringConvertible` +/// protocol. When stringifying a non-`TestOutputStringConvertible` type, this +/// function will return the value's debug description and then its +/// normal description if available and in that order. Otherwise it +/// will return the result of constructing a string from the value. +/// +/// - SeeAlso: `TestOutputStringConvertible` +public func stringify(_ value: T?) -> String { + guard let value = value else { return "nil" } + + if let value = value as? TestOutputStringConvertible { + return value.testDescription + } + + if let value = value as? CustomDebugStringConvertible { + return value.debugDescription + } + + return String(describing: value) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@objc public class NMBStringer: NSObject { + @objc public class func stringify(_ obj: Any?) -> String { + return Nimble.stringify(obj) + } +} +#endif + +// MARK: Collection Type Stringers + +/// Attempts to generate a pretty type string for a given value. If the value is of a Objective-C +/// collection type, or a subclass thereof, (e.g. `NSArray`, `NSDictionary`, etc.). +/// This function will return the type name of the root class of the class cluster for better +/// readability (e.g. `NSArray` instead of `__NSArrayI`). +/// +/// For values that don't have a type of an Objective-C collection, this function returns the +/// default type description. +/// +/// - parameter value: A value that will be used to determine a type name. +/// +/// - returns: The name of the class cluster root class for Objective-C collection types, or the +/// the `dynamicType` of the value for values of any other type. +public func prettyCollectionType(_ value: T) -> String { + switch value { + case is NSArray: + return String(describing: NSArray.self) + case is NSDictionary: + return String(describing: NSDictionary.self) + case is NSSet: + return String(describing: NSSet.self) + case is NSIndexSet: + return String(describing: NSIndexSet.self) + default: + return String(describing: value) + } +} + +/// Returns the type name for a given collection type. This overload is used by Swift +/// collection types. +/// +/// - parameter collection: A Swift `CollectionType` value. +/// +/// - returns: A string representing the `dynamicType` of the value. +public func prettyCollectionType(_ collection: T) -> String { + return String(describing: type(of: collection)) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..9170541 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,389 @@ +#import + +@class NMBExpectation; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; +@protocol NMBMatcher; + + +NS_ASSUME_NONNULL_BEGIN + + +#define NIMBLE_OVERLOADABLE __attribute__((overloadable)) +#define NIMBLE_EXPORT FOUNDATION_EXPORT +#define NIMBLE_EXPORT_INLINE FOUNDATION_STATIC_INLINE + +#define NIMBLE_VALUE_OF(VAL) ({ \ + __typeof__((VAL)) val = (VAL); \ + [NSValue valueWithBytes:&val objCType:@encode(__typeof__((VAL)))]; \ +}) + +#ifdef NIMBLE_DISABLE_SHORT_SYNTAX +#define NIMBLE_SHORT(PROTO, ORIGINAL) +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) +#else +#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); } +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE NIMBLE_OVERLOADABLE PROTO { return (ORIGINAL); } +#endif + + + +#define DEFINE_NMB_EXPECT_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBExpectation *NMB_expect(TYPE(^actualBlock)(void), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(void), NSString *file, NSUInteger line); + + // overloaded dispatch for nils - expect(nil) + DEFINE_NMB_EXPECT_OVERLOAD(void*, nil) + DEFINE_NMB_EXPECT_OVERLOAD(NSRange, NIMBLE_VALUE_OF(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(float, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(double, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned char, @(actualBlock())) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_NMB_EXPECT_OVERLOAD(BOOL, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char *, @(actualBlock())) + + +#undef DEFINE_NMB_EXPECT_OVERLOAD + + + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line); + + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_equal(TYPE expectedValue) { \ + return NMB_equal((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id equal(TYPE expectedValue), NMB_equal(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_equal(__nullable id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id equal(__nullable id expectedValue), + NMB_equal(expectedValue)); + + // overloaded dispatch for nils - expect(nil) + DEFINE_OVERLOAD(void*__nullable, (id)nil) + DEFINE_OVERLOAD(NSRange, NIMBLE_VALUE_OF(expectedValue)) + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_OVERLOAD(BOOL, @(expectedValue)) + DEFINE_OVERLOAD(char *, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_haveCount(TYPE expectedValue) { \ + return NMB_haveCount((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id haveCount(TYPE expectedValue), \ + NMB_haveCount(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_haveCount(id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id haveCount(id expectedValue), + NMB_haveCount(expectedValue)); + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ + return NMB_beCloseTo((NSNumber *)(EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ + NMB_beCloseTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), + NMB_beCloseTo(expectedValue)); + + // it would be better to only overload float & double, but zero becomes ambigious + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAnInstanceOf(Class expectedClass) { + return NMB_beAnInstanceOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAKindOf(Class expectedClass) { + return NMB_beAKindOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE id beginWith(id itemElementOrSubstring) { + return NMB_beginWith(itemElementOrSubstring); +} + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThan(TYPE expectedValue) { \ + return NMB_beGreaterThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThan(NSNumber *expectedValue) { + return NMB_beGreaterThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beGreaterThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThanOrEqualTo(TYPE expectedValue), \ + NMB_beGreaterThanOrEqualTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beGreaterThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(id beIdenticalTo(id expectedInstance), + NMB_beIdenticalTo(expectedInstance)); + +NIMBLE_EXPORT id NMB_be(id expectedInstance); +NIMBLE_SHORT(id be(id expectedInstance), + NMB_be(expectedInstance)); + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThan(TYPE expectedValue) { \ + return NMB_beLessThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThan(TYPE expectedValue), \ + NMB_beLessThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThan(NSNumber *expectedValue) { + return NMB_beLessThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beLessThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThanOrEqualTo(TYPE expectedValue), \ + NMB_beLessThanOrEqualTo(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beLessThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beTruthy(void); +NIMBLE_SHORT(id beTruthy(void), + NMB_beTruthy()); + +NIMBLE_EXPORT id NMB_beFalsy(void); +NIMBLE_SHORT(id beFalsy(void), + NMB_beFalsy()); + +NIMBLE_EXPORT id NMB_beTrue(void); +NIMBLE_SHORT(id beTrue(void), + NMB_beTrue()); + +NIMBLE_EXPORT id NMB_beFalse(void); +NIMBLE_SHORT(id beFalse(void), + NMB_beFalse()); + +NIMBLE_EXPORT id NMB_beNil(void); +NIMBLE_SHORT(id beNil(void), + NMB_beNil()); + +NIMBLE_EXPORT id NMB_beEmpty(void); +NIMBLE_SHORT(id beEmpty(void), + NMB_beEmpty()); + +NIMBLE_EXPORT id 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 NMB_containElementSatisfying(BOOL(^predicate)(id)); +NIMBLE_SHORT(id containElementSatisfying(BOOL(^predicate)(id)), + NMB_containElementSatisfying(predicate)); + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(id endWith(id itemElementOrSubstring), + NMB_endWith(itemElementOrSubstring)); + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), + NMB_raiseException()); + +NIMBLE_EXPORT id NMB_match(id expectedValue); +NIMBLE_SHORT(id match(id expectedValue), + NMB_match(expectedValue)); + +NIMBLE_EXPORT id NMB_allPass(id matcher); +NIMBLE_SHORT(id allPass(id matcher), + NMB_allPass(matcher)); + +NIMBLE_EXPORT id 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 NMB_satisfyAllOfWithMatchers(id matchers); +#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__]) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__) +#endif + +// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__, +// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout +// and action arguments. See https://github.com/Quick/Quick/pull/185 for details. +typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void))); +typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void))); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line); +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +#define NMB_waitUntilTimeout NMB_waitUntilTimeoutBuilder(@(__FILE__), __LINE__) +#define NMB_waitUntil NMB_waitUntilBuilder(@(__FILE__), __LINE__) + +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define expect(...) NMB_expect(^{ return (__VA_ARGS__); }, @(__FILE__), __LINE__) +#define expectAction(BLOCK) NMB_expectAction((BLOCK), @(__FILE__), __LINE__) +#define failWithMessage(msg) NMB_failWithMessage(msg, @(__FILE__), __LINE__) +#define fail() failWithMessage(@"fail() always fails") + + +#define waitUntilTimeout NMB_waitUntilTimeout +#define waitUntil NMB_waitUntil + +#undef NIMBLE_VALUE_OF + +#endif + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..670415b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,161 @@ +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(void), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line) { + return NMB_expect(^id{ + actualBlock(); + return nil; + }, file, line); +} + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line) { + return [NMBExpectation failWithMessage:msg file:file line:line]; +} + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass) { + return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass) { + return [NMBObjCMatcher beAKindOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001]; +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring) { + return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT id NMB_be(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beTruthy() { + return [NMBObjCMatcher beTruthyMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalsy() { + return [NMBObjCMatcher beFalsyMatcher]; +} + +NIMBLE_EXPORT id NMB_beTrue() { + return [NMBObjCMatcher beTrueMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalse() { + return [NMBObjCMatcher beFalseMatcher]; +} + +NIMBLE_EXPORT id NMB_beNil() { + return [NMBObjCMatcher beNilMatcher]; +} + +NIMBLE_EXPORT id NMB_beEmpty() { + return [NMBObjCMatcher beEmptyMatcher]; +} + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) { + NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; + + if (itemOrSubstring) { + [itemOrSubstringArray addObject:itemOrSubstring]; + + va_list args; + va_start(args, itemOrSubstring); + id next; + while ((next = va_arg(args, id))) { + [itemOrSubstringArray addObject:next]; + } + va_end(args); + } + + return [NMBObjCMatcher containMatcher:itemOrSubstringArray]; +} + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)) { + return [NMBObjCMatcher containElementSatisfyingMatcher:predicate]; +} + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring) { + return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_equal(__nullable id expectedValue) { + return [NMBObjCMatcher equalMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_haveCount(id expectedValue) { + return [NMBObjCMatcher haveCountMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_match(id expectedValue) { + return [NMBObjCMatcher matchMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_allPass(id expectedValue) { + return [NMBObjCMatcher allPassMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAnyOfMatcher:matchers]; +} + +NIMBLE_EXPORT id NMB_satisfyAllOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAllOfMatcher:matchers]; +} + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..e6e0272 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h @@ -0,0 +1,11 @@ +#import +#import + +@interface NMBExceptionCapture : NSObject + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..52684b7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m @@ -0,0 +1,35 @@ +#import "NMBExceptionCapture.h" + +@interface NMBExceptionCapture () +@property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); +@property (nonatomic, copy) void(^ _Nullable finally)(void); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..7938bca --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h @@ -0,0 +1,18 @@ +@class NSString; + +/** + * Returns a string appropriate for displaying in test output + * from the provided value. + * + * @param anyObject A value that will show up in a test's output. + * + * @return The string that is returned can be + * customized per type by conforming a type to the `TestOutputStringConvertible` + * protocol. When stringifying a non-`TestOutputStringConvertible` type, this + * function will return the value's debug description and then its + * normal description if available and in that order. Otherwise it + * will return the result of constructing a string from the value. + * + * @see `TestOutputStringConvertible` + */ +extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..31a80d6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,11 @@ +#import "NMBStringify.h" + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..fa5030a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -0,0 +1,83 @@ +#import +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +#pragma mark - Method Swizzling + +/// Swaps the implementations between two instance methods. +/// +/// @param class The class containing `originalSelector`. +/// @param originalSelector Original method to replace. +/// @param replacementSelector Replacement method. +void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method replacementMethod = class_getInstanceMethod(class, replacementSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(replacementMethod), + method_getTypeEncoding(replacementMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + replacementSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, replacementMethod); + } +} + +#pragma mark - Private + +@interface XCTestObservationCenter (Private) +- (void)_addLegacyTestObserver:(id)observer; +@end + +@implementation XCTestObservationCenter (Register) + +/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary +/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early +/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. +/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, +/// falling back to registering after the first normal observer if this private method ever changes. ++ (void)load { + if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { + // Swizzle -_addLegacyTestObserver: + swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); + } else { + // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented + swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); + } +} + +#pragma mark - Replacement Methods + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +- (void)NMB_original__addLegacyTestObserver:(id)observer { + [self NMB_original__addLegacyTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) +- (void)NMB_original_addTestObserver:(id)observer { + [self NMB_original_addTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml new file mode 100644 index 0000000..f003326 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml @@ -0,0 +1,2 @@ +disabled_rules: + - line_length diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift @@ -0,0 +1,37 @@ +import XCTest +@testable import NimbleTests + +// This is the entry point for NimbleTests on Linux + +XCTMain([ + testCase(AsyncTest.allTests), + testCase(SynchronousTest.allTests), + testCase(UserDescriptionTest.allTests), + + // Matchers + testCase(AllPassTest.allTests), + testCase(BeAKindOfSwiftTest.allTests), + testCase(BeAnInstanceOfTest.allTests), + testCase(BeCloseToTest.allTests), + testCase(BeginWithTest.allTests), + testCase(BeGreaterThanOrEqualToTest.allTests), + testCase(BeGreaterThanTest.allTests), + testCase(BeIdenticalToObjectTest.allTests), + testCase(BeIdenticalToTest.allTests), + testCase(BeLessThanOrEqualToTest.allTests), + testCase(BeLessThanTest.allTests), + testCase(BeTruthyTest.allTests), + testCase(BeTrueTest.allTests), + testCase(BeFalsyTest.allTests), + testCase(BeFalseTest.allTests), + testCase(BeNilTest.allTests), + testCase(ContainTest.allTests), + testCase(EndWithTest.allTests), + testCase(EqualTest.allTests), + testCase(HaveCountTest.allTests), + testCase(MatchTest.allTests), + // testCase(RaisesExceptionTest.allTests), + testCase(ThrowErrorTest.allTests), + testCase(SatisfyAnyOfTest.allTests), + testCase(PostNotificationTest.allTests), +]) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..c44b9e6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,257 @@ +import Dispatch +import Foundation +import XCTest +import Nimble + +final class AsyncTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AsyncTest) -> () throws -> Void)] { + return [ + ("testToEventuallyPositiveMatches", testToEventuallyPositiveMatches), + ("testToEventuallyNegativeMatches", testToEventuallyNegativeMatches), + ("testWaitUntilWithCustomDefaultsTimeout", testWaitUntilWithCustomDefaultsTimeout), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ("testSubjectUnderTestIsReleasedFromMemory", testSubjectUnderTestIsReleasedFromMemory), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testToEventuallyPositiveMatches() { + var value = 0 + deferToMainQueue { value = 1 } + expect { value }.toEventually(equal(1)) + + deferToMainQueue { value = 0 } + expect { value }.toEventuallyNot(equal(1)) + } + + func testToEventuallyNegativeMatches() { + let value = 0 + failsWithErrorMessage("expected to eventually not equal <0>, got <0>") { + expect { value }.toEventuallyNot(equal(0)) + } + failsWithErrorMessage("expected to eventually equal <1>, got <0>") { + expect { value }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventuallyNot(equal(0)) + } + } + + func testToEventuallyWithCustomDefaultTimeout() { + AsyncDefaults.Timeout = 2 + defer { + AsyncDefaults.Timeout = 1 + } + + var value = 0 + + let sleepThenSetValueTo: (Int) -> Void = { newValue in + Thread.sleep(forTimeInterval: 1.1) + value = newValue + } + + var asyncOperation: () -> Void = { sleepThenSetValueTo(1) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventually(equal(1)) + + asyncOperation = { sleepThenSetValueTo(0) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventuallyNot(equal(1)) + } + + func testWaitUntilWithCustomDefaultsTimeout() { + AsyncDefaults.Timeout = 5 + defer { + AsyncDefaults.Timeout = 1 + } + waitUntil { done in + Thread.sleep(forTimeInterval: 4.8) + done() + } + } + + func testWaitUntilPositiveMatches() { + waitUntil { done in + done() + } + waitUntil { done in + deferToMainQueue { + done() + } + } + } + + func testWaitUntilTimesOutIfNotCalled() { + failsWithErrorMessage("Waited more than 1.0 second") { + waitUntil(timeout: 1) { _ in return } + } + } + + func testWaitUntilTimesOutWhenExceedingItsTime() { + var waiting = true + failsWithErrorMessage("Waited more than 0.01 seconds") { + waitUntil(timeout: 0.01) { done in + let asyncOperation: () -> Void = { + Thread.sleep(forTimeInterval: 0.1) + done() + waiting = false + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + } + } + + // "clear" runloop to ensure this test doesn't poison other tests + repeat { + RunLoop.main.run(until: Date().addingTimeInterval(0.2)) + } while(waiting) + } + + func testWaitUntilNegativeMatches() { + failsWithErrorMessage("expected to equal <2>, got <1>") { + waitUntil { done in + Thread.sleep(forTimeInterval: 0.1) + expect(1).to(equal(2)) + done() + } + } + } + + func testWaitUntilDetectsStalledMainThreadActivity() { + let msg = "-waitUntil() timed out but was unable to run the timeout handler because the main thread is unresponsive (0.5 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." + failsWithErrorMessage(msg) { + waitUntil(timeout: 1) { done in + Thread.sleep(forTimeInterval: 5.0) + done() + } + } + } + + func testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed() { + // Currently we are unable to catch Objective-C exceptions when built by the Swift Package Manager +#if !SWIFT_PACKAGE + let referenceLine = #line + 9 + var msg = "Unexpected exception raised: Nested async expectations are not allowed " + msg += "to avoid creating flaky tests." + msg += "\n\n" + msg += "The call to\n\t" + msg += "expect(...).toEventually(...) at \(#file):\(referenceLine + 7)\n" + msg += "triggered this exception because\n\t" + msg += "waitUntil(...) at \(#file):\(referenceLine + 1)\n" + msg += "is currently managing the main run loop." + failsWithErrorMessage(msg) { // reference line + waitUntil(timeout: 2.0) { done in + var protected: Int = 0 + DispatchQueue.main.async { + protected = 1 + } + + expect(protected).toEventually(equal(1)) + done() + } + } +#endif + } + + func testWaitUntilErrorsIfDoneIsCalledMultipleTimes() { + failsWithErrorMessage("waitUntil(..) expects its completion closure to be only called once") { + waitUntil { done in + deferToMainQueue { + done() + done() + } + } + } + } + + func testWaitUntilMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + waitUntil { done in done() } + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + func testToEventuallyMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + expect(1).toEventually(equal(2)) + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + final class ClassUnderTest { + var deinitCalled: (() -> Void)? + var count = 0 + deinit { deinitCalled?() } + } + + func testSubjectUnderTestIsReleasedFromMemory() { + var subject: ClassUnderTest? = ClassUnderTest() + + if let sub = subject { + expect(sub.count).toEventually(equal(0), timeout: 0.1) + expect(sub.count).toEventuallyNot(equal(1), timeout: 0.1) + } + + waitUntil(timeout: 0.5) { done in + subject?.deinitCalled = { + done() + } + + deferToMainQueue { subject = nil } + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift @@ -0,0 +1,7 @@ +import Foundation + +class ObjectWithLazyProperty { + init() {} + lazy var value: String = "hello" + lazy var anotherValue: String = { return "world" }() +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..08a67c6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +extension XCTestCaseProvider { + var allTestNames: [String] { + return type(of: self).allTests.map({ name, _ in + return name + }) + } +} + +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } +} + +extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..a1bbc68 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,100 @@ +import Dispatch +import Foundation +@testable import Nimble +import XCTest + +func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () throws -> Void) { + var filePath = file + var lineNumber = line + + let recorder = AssertionRecorder() + withAssertionHandler(recorder, closure: closure) + + for msg in messages { + var lastFailure: AssertionRecord? + var foundFailureMessage = false + + for assertion in recorder.assertions where assertion.message.stringValue == msg && !assertion.success { + lastFailure = assertion + foundFailureMessage = true + break + } + + if foundFailureMessage { + continue + } + + if preferOriginalSourceLocation { + if let failure = lastFailure { + filePath = failure.location.file + lineNumber = failure.location.line + } + } + + let message: String + if let lastFailure = lastFailure { + message = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\"" + } else { + let knownFailures = recorder.assertions.filter { !$0.success }.map { $0.message.stringValue } + let knownFailuresJoined = knownFailures.joined(separator: ", ") + message = "Expected error message (\(msg)), got (\(knownFailuresJoined))\n\nAssertions Received:\n\(recorder.assertions)" + } + NimbleAssertionHandler.assert(false, + message: FailureMessage(stringValue: message), + location: SourceLocation(file: filePath, line: lineNumber)) + } +} + +func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + return failsWithErrorMessage( + [message], + file: file, + line: line, + preferOriginalSourceLocation: preferOriginalSourceLocation, + closure: closure + ) +} + +func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + failsWithErrorMessage("\(message) (use beNil() to match nils)", file: file, line: line, preferOriginalSourceLocation: preferOriginalSourceLocation, closure: closure) +} + +func deferToMainQueue(action: @escaping () -> Void) { + DispatchQueue.main.async { + Thread.sleep(forTimeInterval: 0.01) + action() + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +public class NimbleHelper: NSObject { + @objc public class func expectFailureMessage(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessages(_ messages: [NSString], block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(messages.map({String(describing: $0)}), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessageForNil(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessageForNil(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } +} +#endif + +extension Date { + init(dateTimeString: String) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + let date = dateFormatter.date(from: dateTimeString)! + self.init(timeInterval: 0, since: date) + } +} + +extension NSDate { + convenience init(dateTimeString: String) { + let date = Date(dateTimeString: dateTimeString) + self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift @@ -0,0 +1,9 @@ +import Foundation + +#if os(Linux) + extension NSNotification.Name { + init(_ rawValue: String) { + self.init(rawValue: rawValue) + } + } +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift @@ -0,0 +1,126 @@ +import XCTest +import Nimble + +/// Add operators to `Optional` for conforming `Comparable` that removed in Swift 3.0 +extension Optional where Wrapped: Comparable { + static func < (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } + } + + static func > (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } + } + + static func <= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l <= r + default: + return !(rhs < lhs) + } + } + + static func >= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } + } +} + +final class AllPassTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AllPassTest) -> () throws -> Void)] { + return [ + ("testAllPassArray", testAllPassArray), + ("testAllPassMatcher", testAllPassMatcher), + ("testAllPassCollectionsWithOptionalsDontWork", testAllPassCollectionsWithOptionalsDontWork), + ("testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer", testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer), + ("testAllPassSet", testAllPassSet), + ("testAllPassWithNilAsExpectedValue", testAllPassWithNilAsExpectedValue), + ] + } + + func testAllPassArray() { + expect([1, 2, 3, 4]).to(allPass({$0 < 5})) + expect([1, 2, 3, 4]).toNot(allPass({$0 > 5})) + + failsWithErrorMessage( + "expected to all pass a condition, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass({$0 < 3})) + } + failsWithErrorMessage("expected to not all pass a condition") { + expect([1, 2, 3, 4]).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage( + "expected to all be something, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass("be something", {$0 < 3})) + } + failsWithErrorMessage("expected to not all be something") { + expect([1, 2, 3, 4]).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassMatcher() { + expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) + expect([1, 2, 3, 4]).toNot(allPass(beGreaterThan(5))) + + failsWithErrorMessage( + "expected to all be less than <3>, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass(beLessThan(3))) + } + failsWithErrorMessage("expected to not all be less than <5>") { + expect([1, 2, 3, 4]).toNot(allPass(beLessThan(5))) + } + } + + func testAllPassCollectionsWithOptionalsDontWork() { + failsWithErrorMessage("expected to all be nil, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass(beNil())) + } + failsWithErrorMessage("expected to all pass a condition, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass({$0 == nil})) + } + } + + func testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer() { + expect([nil, nil, nil] as [Int?]).to(allPass({$0! == nil})) + expect([nil, 1, nil] as [Int?]).toNot(allPass({$0! == nil})) + expect([1, 1, 1] as [Int?]).to(allPass({$0! == 1})) + expect([1, 1, nil] as [Int?]).toNot(allPass({$0! == 1})) + expect([1, 2, 3] as [Int?]).to(allPass({$0! < 4})) + expect([1, 2, 3] as [Int?]).toNot(allPass({$0! < 3})) + expect([1, 2, nil] as [Int?]).to(allPass({$0! < 3})) + } + + func testAllPassSet() { + expect(Set([1, 2, 3, 4])).to(allPass({$0 < 5})) + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 > 5})) + + failsWithErrorMessage("expected to not all pass a condition") { + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage("expected to not all be something") { + expect(Set([1, 2, 3, 4])).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassWithNilAsExpectedValue() { + failsWithErrorMessageForNil("expected to all pass") { + expect(nil as [Int]?).to(allPass(beLessThan(5))) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..bb9041b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +private class TestNull: NSNull {} +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfSwiftTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + enum TestEnum { + case one, two + } + + func testPositiveMatch() { + expect(1).to(beAKindOf(Int.self)) + expect(1).toNot(beAKindOf(String.self)) + expect("turtle string").to(beAKindOf(String.self)) + expect("turtle string").toNot(beAKindOf(TestClassConformingToProtocol.self)) + + expect(TestEnum.one).to(beAKindOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAKindOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).to(beAKindOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAKindOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAKindOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).to(beAKindOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAKindOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessage("expected to not be a kind of Int, got ") { + expect(1).toNot(beAKindOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to not be a kind of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).toNot(beAKindOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be a kind of String, got ") { + expect(1).to(beAKindOf(String.self)) + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfObjCTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + func testPositiveMatch() { + expect(TestNull()).to(beAKindOf(NSNull.self)) + expect(NSObject()).to(beAKindOf(NSObject.self)) + expect(NSNumber(value: 1)).toNot(beAKindOf(NSDate.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be a kind of NSNull, got ") { + expect(nil as NSNull?).toNot(beAKindOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be a kind of NSString, got ") { + expect(nil as NSString?).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to be a kind of NSString, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to not be a kind of NSNumber, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).toNot(beAKindOf(NSNumber.self)) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..aeea28a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAnInstanceOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAnInstanceOfTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testPositiveMatchSwiftTypes", testPositiveMatchSwiftTypes), + ("testFailureMessages", testFailureMessages), + ("testFailureMessagesSwiftTypes", testFailureMessagesSwiftTypes), + ] + } + + func testPositiveMatch() { + expect(NSNull()).to(beAnInstanceOf(NSNull.self)) + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(NSDate.self)) + } + + enum TestEnum { + case one, two + } + + func testPositiveMatchSwiftTypes() { + expect(1).to(beAnInstanceOf(Int.self)) + expect("test").to(beAnInstanceOf(String.self)) + + expect(TestEnum.one).to(beAnInstanceOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAnInstanceOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAnInstanceOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be an instance of NSNull, got ") { + expect(nil as NSNull?).toNot(beAnInstanceOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be an instance of NSString, got ") { + expect(nil as NSString?).to(beAnInstanceOf(NSString.self)) + } +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let numberTypeName = "__NSCFNumber" +#else + let numberTypeName = "NSNumber" +#endif + failsWithErrorMessage("expected to be an instance of NSString, got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).to(beAnInstanceOf(NSString.self)) + } + failsWithErrorMessage("expected to not be an instance of \(numberTypeName), got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(type(of: NSNumber(value: 1)))) + } + } + + func testFailureMessagesSwiftTypes() { + failsWithErrorMessage("expected to not be an instance of Int, got ") { + expect(1).toNot(beAnInstanceOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to be an instance of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).to(beAnInstanceOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be an instance of String, got ") { + expect(1).to(beAnInstanceOf(String.self)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..cb7a3ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift @@ -0,0 +1,160 @@ +import Foundation +import XCTest +import Nimble + +final class BeCloseToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeCloseToTest) -> () throws -> Void)] { + return [ + ("testBeCloseTo", testBeCloseTo), + ("testBeCloseToWithin", testBeCloseToWithin), + ("testBeCloseToWithNSNumber", testBeCloseToWithNSNumber), + ("testBeCloseToWithDate", testBeCloseToWithDate), + ("testBeCloseToWithNSDate", testBeCloseToWithNSDate), + ("testBeCloseToOperator", testBeCloseToOperator), + ("testBeCloseToWithinOperator", testBeCloseToWithinOperator), + ("testPlusMinusOperator", testPlusMinusOperator), + ("testBeCloseToOperatorWithDate", testBeCloseToOperatorWithDate), + ("testBeCloseToWithinOperatorWithDate", testBeCloseToWithinOperatorWithDate), + ("testPlusMinusOperatorWithDate", testPlusMinusOperatorWithDate), + ("testBeCloseToArray", testBeCloseToArray), + ("testBeCloseToWithCGFloat", testBeCloseToWithCGFloat), + ] + } + + func testBeCloseTo() { + expect(1.2).to(beCloseTo(1.2001)) + expect(1.2 as CDouble).to(beCloseTo(1.2001)) + expect(1.2 as Float).to(beCloseTo(1.2001)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 0.0001), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001)) + } + } + + func testBeCloseToWithin() { + expect(1.2).to(beCloseTo(9.300, within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithNSNumber() { + expect(NSNumber(value: 1.2)).to(beCloseTo(9.300, within: 10)) + expect(NSNumber(value: 1.2)).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + expect(1.2).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithCGFloat() { + expect(CGFloat(1.2)).to(beCloseTo(1.2001)) + expect(CGFloat(1.2)).to(beCloseTo(CGFloat(1.2001))) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(Date(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToWithNSDate() { + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(NSDate(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = NSDate(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToOperator() { + expect(1.2) ≈ 1.2001 + expect(1.2 as CDouble) ≈ 1.2001 + + failsWithErrorMessage("expected to be close to <1.2002> (within 0.0001), got <1.2>") { + expect(1.2) ≈ 1.2002 + } + } + + func testBeCloseToWithinOperator() { + expect(1.2) ≈ (9.300, 10) + expect(1.2) == (9.300, 10) + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ (1.0, 0.1) + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == (1.0, 0.1) + } + } + + func testPlusMinusOperator() { + expect(1.2) ≈ 9.300 ± 10 + expect(1.2) == 9.300 ± 10 + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ 1.0 ± 0.1 + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == 1.0 ± 0.1 + } + } + + func testBeCloseToOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:00") + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.0001), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate + } + } + + func testBeCloseToWithinOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (expectedDate, 0.004) + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (expectedDate, 0.004) + } + } + + func testPlusMinusOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate ± 0.004 + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == expectedDate ± 0.004 + } + } + + func testBeCloseToArray() { + expect([0.0, 1.1, 2.2]) ≈ [0.0001, 1.1001, 2.2001] + expect([0.0, 1.1, 2.2]).to(beCloseTo([0.1, 1.2, 2.3], within: 0.1)) + + failsWithErrorMessage("expected to be close to <[0, 1]> (each within 0.0001), got <[0, 1.1]>") { + expect([0.0, 1.1]) ≈ [0.0, 1.0] + } + failsWithErrorMessage("expected to be close to <[0.2, 1.2]> (each within 0.1), got <[0, 1.1]>") { + expect([0.0, 1.1]).to(beCloseTo([0.2, 1.2], within: 0.1)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..067ddeb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift @@ -0,0 +1,82 @@ +import Foundation +import XCTest +import Nimble + +final class BeEmptyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeEmptyTest) -> () throws -> Void)] { + return [ + ("testBeEmptyPositive", testBeEmptyPositive), + ("testBeEmptyNegative", testBeEmptyNegative), + ] + } + + func testBeEmptyPositive() { + expect([] as [Int]).to(beEmpty()) + expect([1]).toNot(beEmpty()) + + expect([] as [CInt]).to(beEmpty()) + expect([1] as [CInt]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary() as? [Int: Int]).to(beEmpty()) + expect(NSDictionary(object: 1, forKey: 1 as NSNumber) as? [Int: Int]).toNot(beEmpty()) +#endif + + expect([Int: Int]()).to(beEmpty()) + expect(["hi": 1]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray() as? [Int]).to(beEmpty()) + expect(NSArray(array: [1]) as? [Int]).toNot(beEmpty()) +#endif + + expect(NSSet()).to(beEmpty()) + expect(NSSet(array: [NSNumber(value: 1)])).toNot(beEmpty()) + + expect(NSIndexSet()).to(beEmpty()) + expect(NSIndexSet(index: 1)).toNot(beEmpty()) + + expect(NSString()).to(beEmpty()) + expect(NSString(string: "hello")).toNot(beEmpty()) + + expect("").to(beEmpty()) + expect("foo").toNot(beEmpty()) + } + + func testBeEmptyNegative() { + failsWithErrorMessageForNil("expected to be empty, got ") { + expect(nil as NSString?).to(beEmpty()) + } + failsWithErrorMessageForNil("expected to not be empty, got ") { + expect(nil as [CInt]?).toNot(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSArray()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <[1]>") { + expect([1]).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <{()}>") { + expect(NSSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <{(1)}>") { + expect(NSSet(object: NSNumber(value: 1))).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSIndexSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <(1)>") { + expect(NSIndexSet(index: 1)).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <>") { + expect("").toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got ") { + expect("foo").to(beEmpty()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..bd73361 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testGreaterThanOrEqualTo", testGreaterThanOrEqualTo), + ("testGreaterThanOrEqualToOperator", testGreaterThanOrEqualToOperator), + ] + } + + func testGreaterThanOrEqualTo() { + expect(10).to(beGreaterThanOrEqualTo(10)) + expect(10).to(beGreaterThanOrEqualTo(2)) + expect(1).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 1)).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 2)).to(beGreaterThanOrEqualTo(NSNumber(value: 2))) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(1).to(beGreaterThanOrEqualTo(NSNumber(value: 0))) +#endif + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <0>") { + expect(0).to(beGreaterThanOrEqualTo(2)) + return + } + failsWithErrorMessage("expected to not be greater than or equal to <1>, got <1>") { + expect(1).toNot(beGreaterThanOrEqualTo(1)) + return + } + failsWithErrorMessageForNil("expected to be greater than or equal to <-2>, got ") { + expect(nil as Int?).to(beGreaterThanOrEqualTo(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than or equal to <1>, got ") { + expect(nil as Int?).toNot(beGreaterThanOrEqualTo(1)) + } + } + + func testGreaterThanOrEqualToOperator() { + expect(0) >= 0 + expect(1) >= 0 + expect(NSNumber(value: 1)) >= 1 + expect(NSNumber(value: 1)) >= NSNumber(value: 1) + expect(2.5) >= 2.5 + expect(2.5) >= 2 + expect(Float(2.5)) >= Float(2.5) + expect(Float(2.5)) >= 2 + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <1>") { + expect(1) >= 2 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..9c33e4b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanTest) -> () throws -> Void)] { + return [ + ("testGreaterThan", testGreaterThan), + ("testGreaterThanOperator", testGreaterThanOperator), + ] + } + + func testGreaterThan() { + expect(10).to(beGreaterThan(2)) + expect(1).toNot(beGreaterThan(2)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 3)).to(beGreaterThan(2)) +#else + expect(NSNumber(value: 3)).to(beGreaterThan(2 as NSNumber)) +#endif + expect(NSNumber(value: 1)).toNot(beGreaterThan(NSNumber(value: 2))) + + failsWithErrorMessage("expected to be greater than <2>, got <0>") { + expect(0).to(beGreaterThan(2)) + } + failsWithErrorMessage("expected to not be greater than <0>, got <1>") { + expect(1).toNot(beGreaterThan(0)) + } + failsWithErrorMessageForNil("expected to be greater than <-2>, got ") { + expect(nil as Int?).to(beGreaterThan(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than <0>, got ") { + expect(nil as Int?).toNot(beGreaterThan(0)) + } + } + + func testGreaterThanOperator() { + expect(1) > 0 + expect(NSNumber(value: 1)) > NSNumber(value: 0) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 1)) > 0 +#else + expect(NSNumber(value: 1)) > 0 as NSNumber +#endif + expect(2.5) > 1.5 + expect(Float(2.5)) > Float(1.5) + + failsWithErrorMessage("expected to be greater than <2>, got <1>") { + expect(1) > 2 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift @@ -0,0 +1,64 @@ +import Foundation +import XCTest +import Nimble + +final class BeIdenticalToObjectTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToObjectTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testFailsOnNils", testFailsOnNils), + ("testOperators", testOperators), + ] + } + + private class BeIdenticalToObjectTester {} + private let testObjectA = BeIdenticalToObjectTester() + private let testObjectB = BeIdenticalToObjectTester() + + func testBeIdenticalToPositive() { + expect(self.testObjectA).to(beIdenticalTo(testObjectA)) + } + + func testBeIdenticalToNegative() { + expect(self.testObjectA).toNot(beIdenticalTo(testObjectB)) + } + + func testBeIdenticalToPositiveMessage() { + let message = String(describing: NSString(format: "expected to be identical to <%p>, got <%p>", + unsafeBitCast(testObjectB, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).to(beIdenticalTo(self.testObjectB)) + } + } + + func testBeIdenticalToNegativeMessage() { + let message = String(describing: NSString(format: "expected to not be identical to <%p>, got <%p>", + unsafeBitCast(testObjectA, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testFailsOnNils() { + let message1 = String(describing: NSString(format: "expected to be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message1) { + expect(nil as BeIdenticalToObjectTester?).to(beIdenticalTo(self.testObjectA)) + } + + let message2 = String(describing: NSString(format: "expected to not be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message2) { + expect(nil as BeIdenticalToObjectTester?).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testOperators() { + expect(self.testObjectA) === testObjectA + expect(self.testObjectA) !== testObjectB + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..6b629b0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift @@ -0,0 +1,68 @@ +import Foundation +import XCTest +@testable import Nimble + +final class BeIdenticalToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testOperators", testOperators), + ("testBeAlias", testBeAlias), + ] + } + + func testBeIdenticalToPositive() { + let value = NSDate() + expect(value).to(beIdenticalTo(value)) + } + + func testBeIdenticalToNegative() { + expect(NSNumber(value: 1)).toNot(beIdenticalTo(NSString(string: "yo"))) + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + } + + func testBeIdenticalToPositiveMessage() { + let num1 = NSNumber(value: 1) + let num2 = NSNumber(value: 2) + let message = "expected to be identical to \(identityAsString(num2)), got \(identityAsString(num1))" + failsWithErrorMessage(message) { + expect(num1).to(beIdenticalTo(num2)) + } + } + + func testBeIdenticalToNegativeMessage() { + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value2)), got \(identityAsString(value1))" + failsWithErrorMessage(message) { + expect(value1).toNot(beIdenticalTo(value2)) + } + } + + func testOperators() { + let value = NSDate() + expect(value) === value + expect(NSNumber(value: 1)) !== NSNumber(value: 2) + } + + func testBeAlias() { + let value = NSDate() + expect(value).to(be(value)) + expect(NSNumber(value: 1)).toNot(be(NSString(string: "turtles"))) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect([1]).toNot(be([1])) + #else + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + #endif + + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value1)), got \(identityAsString(value2))" + failsWithErrorMessage(message) { + expect(value1).toNot(be(value2)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..428ace4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testLessThanOrEqualTo", testLessThanOrEqualTo), + ("testLessThanOrEqualToOperator", testLessThanOrEqualToOperator), + ] + } + + func testLessThanOrEqualTo() { + expect(10).to(beLessThanOrEqualTo(10)) + expect(2).to(beLessThanOrEqualTo(10)) + expect(2).toNot(beLessThanOrEqualTo(1)) + + expect(NSNumber(value: 2)).to(beLessThanOrEqualTo(10)) + expect(NSNumber(value: 2)).toNot(beLessThanOrEqualTo(1)) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(2).to(beLessThanOrEqualTo(NSNumber(value: 10))) + expect(2).toNot(beLessThanOrEqualTo(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than or equal to <0>, got <2>") { + expect(2).to(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessage("expected to not be less than or equal to <0>, got <0>") { + expect(0).toNot(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessageForNil("expected to be less than or equal to <2>, got ") { + expect(nil as Int?).to(beLessThanOrEqualTo(2)) + return + } + failsWithErrorMessageForNil("expected to not be less than or equal to <-2>, got ") { + expect(nil as Int?).toNot(beLessThanOrEqualTo(-2)) + return + } + } + + func testLessThanOrEqualToOperator() { + expect(0) <= 1 + expect(1) <= 1 + + failsWithErrorMessage("expected to be less than or equal to <1>, got <2>") { + expect(2) <= 1 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..90ba1b9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift @@ -0,0 +1,57 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanTest) -> () throws -> Void)] { + return [ + ("testLessThan", testLessThan), + ("testLessThanOperator", testLessThanOperator), + ] + } + + func testLessThan() { + expect(2).to(beLessThan(10)) + expect(2).toNot(beLessThan(1)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 2)).to(beLessThan(10)) + expect(NSNumber(value: 2)).toNot(beLessThan(1)) + + expect(2).to(beLessThan(NSNumber(value: 10))) + expect(2).toNot(beLessThan(NSNumber(value: 1))) +#else + expect(NSNumber(value: 2)).to(beLessThan(10 as NSNumber)) + expect(NSNumber(value: 2)).toNot(beLessThan(1 as NSNumber)) + + expect(2 as NSNumber).to(beLessThan(NSNumber(value: 10))) + expect(2 as NSNumber).toNot(beLessThan(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than <0>, got <2>") { + expect(2).to(beLessThan(0)) + } + failsWithErrorMessage("expected to not be less than <1>, got <0>") { + expect(0).toNot(beLessThan(1)) + } + + failsWithErrorMessageForNil("expected to be less than <2>, got ") { + expect(nil as Int?).to(beLessThan(2)) + } + failsWithErrorMessageForNil("expected to not be less than <-1>, got ") { + expect(nil as Int?).toNot(beLessThan(-1)) + } + } + + func testLessThanOperator() { + expect(0) < 1 +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 0)) < 1 +#else + expect(NSNumber(value: 0)) < 1 as NSNumber +#endif + failsWithErrorMessage("expected to be less than <1>, got <2>") { + expect(2) < 1 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift @@ -0,0 +1,270 @@ +import XCTest +import Nimble +import Foundation + +enum ConvertsToBool: ExpressibleByBooleanLiteral, CustomStringConvertible { + case trueLike, falseLike + + typealias BooleanLiteralType = Bool + + init(booleanLiteral value: Bool) { + switch value { + case true: self = .trueLike + case false: self = .falseLike + } + } + + var boolValue: Bool { + switch self { + case .trueLike: return true + case .falseLike: return false + } + } + + var description: String { + switch self { + case .trueLike: return "TrueLike" + case .falseLike: return "FalseLike" + } + } +} + +final class BeTruthyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTruthyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNonNilTypes", testShouldMatchNonNilTypes), + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchNilTypes", testShouldNotMatchNilTypes), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ("testShouldMatchBoolConvertibleTypesThatConvertToTrue", testShouldMatchBoolConvertibleTypesThatConvertToTrue), + ("testShouldNotMatchBoolConvertibleTypesThatConvertToFalse", testShouldNotMatchBoolConvertibleTypesThatConvertToFalse), + ] + } + + func testShouldMatchNonNilTypes() { + expect(true as Bool?).to(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).to(beTruthy()) + expect(1 as UInt8?).to(beTruthy()) + expect(1 as Int16?).to(beTruthy()) + expect(1 as UInt16?).to(beTruthy()) + expect(1 as Int32?).to(beTruthy()) + expect(1 as UInt32?).to(beTruthy()) + expect(1 as Int64?).to(beTruthy()) + expect(1 as UInt64?).to(beTruthy()) + expect(1 as Float?).to(beTruthy()) + expect(1 as Double?).to(beTruthy()) + expect(1 as Int?).to(beTruthy()) + expect(1 as UInt?).to(beTruthy()) + } + + func testShouldMatchTrue() { + expect(true).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(true).toNot(beTruthy()) + } + } + + func testShouldNotMatchNilTypes() { + expect(false as Bool?).toNot(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).toNot(beTruthy()) + expect(nil as Int8?).toNot(beTruthy()) + expect(nil as UInt8?).toNot(beTruthy()) + expect(nil as Int16?).toNot(beTruthy()) + expect(nil as UInt16?).toNot(beTruthy()) + expect(nil as Int32?).toNot(beTruthy()) + expect(nil as UInt32?).toNot(beTruthy()) + expect(nil as Int64?).toNot(beTruthy()) + expect(nil as UInt64?).toNot(beTruthy()) + expect(nil as Float?).toNot(beTruthy()) + expect(nil as Double?).toNot(beTruthy()) + expect(nil as Int?).toNot(beTruthy()) + expect(nil as UInt?).toNot(beTruthy()) + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(false).to(beTruthy()) + } + } + + func testShouldNotMatchNilBools() { + expect(nil as Bool?).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(nil as Bool?).to(beTruthy()) + } + } + + func testShouldMatchBoolConvertibleTypesThatConvertToTrue() { + expect(ConvertsToBool.trueLike).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(ConvertsToBool.trueLike).toNot(beTruthy()) + } + } + + func testShouldNotMatchBoolConvertibleTypesThatConvertToFalse() { + expect(ConvertsToBool.falseLike).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(ConvertsToBool.falseLike).to(beTruthy()) + } + } +} + +final class BeTrueTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTrueTest) -> () throws -> Void)] { + return [ + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldMatchTrue() { + expect(true).to(beTrue()) + + failsWithErrorMessage("expected to not be true, got ") { + expect(true).toNot(beTrue()) + } + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTrue()) + + failsWithErrorMessage("expected to be true, got ") { + expect(false).to(beTrue()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to not be true, got ") { + expect(nil as Bool?).toNot(beTrue()) + } + + failsWithErrorMessageForNil("expected to be true, got ") { + expect(nil as Bool?).to(beTrue()) + } + } +} + +final class BeFalsyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalsyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNilTypes", testShouldMatchNilTypes), + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldNotMatchNonNilTypes", testShouldNotMatchNonNilTypes), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldMatchNilBools", testShouldMatchNilBools), + ] + } + + func testShouldMatchNilTypes() { + expect(false as Bool?).to(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).to(beFalsy()) + expect(nil as Int8?).to(beFalsy()) + expect(nil as UInt8?).to(beFalsy()) + expect(nil as Int16?).to(beFalsy()) + expect(nil as UInt16?).to(beFalsy()) + expect(nil as Int32?).to(beFalsy()) + expect(nil as UInt32?).to(beFalsy()) + expect(nil as Int64?).to(beFalsy()) + expect(nil as UInt64?).to(beFalsy()) + expect(nil as Float?).to(beFalsy()) + expect(nil as Double?).to(beFalsy()) + expect(nil as Int?).to(beFalsy()) + expect(nil as UInt?).to(beFalsy()) + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalsy()) + + failsWithErrorMessage("expected to be falsy, got ") { + expect(true).to(beFalsy()) + } + } + + func testShouldNotMatchNonNilTypes() { + expect(true as Bool?).toNot(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).toNot(beFalsy()) + expect(1 as UInt8?).toNot(beFalsy()) + expect(1 as Int16?).toNot(beFalsy()) + expect(1 as UInt16?).toNot(beFalsy()) + expect(1 as Int32?).toNot(beFalsy()) + expect(1 as UInt32?).toNot(beFalsy()) + expect(1 as Int64?).toNot(beFalsy()) + expect(1 as UInt64?).toNot(beFalsy()) + expect(1 as Float?).toNot(beFalsy()) + expect(1 as Double?).toNot(beFalsy()) + expect(1 as Int?).toNot(beFalsy()) + expect(1 as UInt?).toNot(beFalsy()) + } + + func testShouldMatchFalse() { + expect(false).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(false).toNot(beFalsy()) + } + } + + func testShouldMatchNilBools() { + expect(nil as Bool?).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(nil as Bool?).toNot(beFalsy()) + } + } +} + +final class BeFalseTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalseTest) -> () throws -> Void)] { + return [ + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalse()) + + failsWithErrorMessage("expected to be false, got ") { + expect(true).to(beFalse()) + } + } + + func testShouldMatchFalse() { + expect(false).to(beFalse()) + + failsWithErrorMessage("expected to not be false, got ") { + expect(false).toNot(beFalse()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to be false, got ") { + expect(nil as Bool?).to(beFalse()) + } + + failsWithErrorMessageForNil("expected to not be false, got ") { + expect(nil as Bool?).toNot(beFalse()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift @@ -0,0 +1,28 @@ +import XCTest +import Nimble + +final class BeNilTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeNilTest) -> () throws -> Void)] { + return [ + ("testBeNil", testBeNil), + ] + } + + func producesNil() -> [Int]? { + return nil + } + + func testBeNil() { + expect(nil as Int?).to(beNil()) + expect(1 as Int?).toNot(beNil()) + expect(self.producesNil()).to(beNil()) + + failsWithErrorMessage("expected to not be nil, got ") { + expect(nil as Int?).toNot(beNil()) + } + + failsWithErrorMessage("expected to be nil, got <1>") { + expect(1 as Int?).to(beNil()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift @@ -0,0 +1,32 @@ +import XCTest +import Nimble + +final class BeVoidTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeVoidTest) -> () throws -> Void)] { + return [ + ("testBeVoid", testBeVoid), + ] + } + + func testBeVoid() { + expect(()).to(beVoid()) + expect(() as ()?).to(beVoid()) + expect(nil as ()?).toNot(beVoid()) + + expect(()) == () + expect(() as ()?) == () + expect(nil as ()?) != () + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(()).toNot(beVoid()) + } + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(() as ()?).toNot(beVoid()) + } + + failsWithErrorMessage("expected to be void, got ") { + expect(nil as ()?).to(beVoid()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..276c7d0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeginWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeginWithTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testNegativeMatches", testNegativeMatches), + ] + } + + func testPositiveMatches() { + expect([1, 2, 3]).to(beginWith(1)) + expect([1, 2, 3]).toNot(beginWith(2)) + + expect("foobar").to(beginWith("foo")) + expect("foobar").toNot(beginWith("oo")) + + expect("foobarfoo").to(beginWith("foo")) + + expect(NSString(string: "foobar").description).to(beginWith("foo")) + expect(NSString(string: "foobar").description).toNot(beginWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(beginWith("a")) + expect(NSArray(array: ["a", "b"])).toNot(beginWith("b")) +#endif + } + + func testNegativeMatches() { + failsWithErrorMessageForNil("expected to begin with , got ") { + expect(nil as NSArray?).to(beginWith(NSString(string: "b"))) + } + failsWithErrorMessageForNil("expected to not begin with , got ") { + expect(nil as NSArray?).toNot(beginWith(NSString(string: "b"))) + } + + failsWithErrorMessage("expected to begin with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(beginWith(2)) + } + failsWithErrorMessage("expected to not begin with <1>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(beginWith(1)) + } + failsWithErrorMessage("expected to begin with , got ") { + expect("batman").to(beginWith("atm")) + } + failsWithErrorMessage("expected to not begin with , got ") { + expect("batman").toNot(beginWith("bat")) + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift @@ -0,0 +1,86 @@ +import Foundation +import XCTest +import Nimble + +final class ContainElementSatisfyingTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainElementSatisfyingTest) -> () throws -> Void)] { + return [ + ("testContainElementSatisfying", testContainElementSatisfying), + ("testContainElementSatisfyingDefaultErrorMessage", testContainElementSatisfyingDefaultErrorMessage), + ("testContainElementSatisfyingSpecificErrorMessage", testContainElementSatisfyingSpecificErrorMessage), + ("testContainElementSatisfyingNegativeCase", + testContainElementSatisfyingNegativeCase), + ("testContainElementSatisfyingNegativeCaseDefaultErrorMessage", + testContainElementSatisfyingNegativeCaseDefaultErrorMessage), + ("testContainElementSatisfyingNegativeCaseSpecificErrorMessage", + testContainElementSatisfyingNegativeCaseSpecificErrorMessage), + ] + } + + func testContainElementSatisfying() { + var orderIndifferentArray = [1, 2, 3] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + + orderIndifferentArray = [3, 1, 2] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + } + + func testContainElementSatisfyingDefaultErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + })) + } + } + + func testContainElementSatisfyingSpecificErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection equal to 4") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + }, "equal to 4")) + } + } + + func testContainElementSatisfyingNegativeCase() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "armadillos" + })) + } + + func testContainElementSatisfyingNegativeCaseDefaultErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + })) + } + } + + func testContainElementSatisfyingNegativeCaseSpecificErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection equal to 'kittens'") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + }, "equal to 'kittens'")) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..1d8a1eb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift @@ -0,0 +1,95 @@ +import Foundation +import XCTest +import Nimble + +final class ContainTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainTest) -> () throws -> Void)] { + return [ + ("testContain", testContain), + ("testContainSubstring", testContainSubstring), + ("testContainObjCSubstring", testContainObjCSubstring), + ("testVariadicArguments", testVariadicArguments), + ("testCollectionArguments", testCollectionArguments), + ] + } + + func testContain() { + expect([1, 2, 3]).to(contain(1)) + expect([1, 2, 3] as [CInt]).to(contain(1 as CInt)) + expect([1, 2, 3] as [CInt]).toNot(contain(4 as CInt)) + expect(["foo", "bar", "baz"]).to(contain("baz")) + expect([1, 2, 3]).toNot(contain(4)) + expect(["foo", "bar", "baz"]).toNot(contain("ba")) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a"])).to(contain(NSString(string: "a"))) + expect(NSArray(array: ["a"])).toNot(contain(NSString(string: "b"))) + expect(NSArray(object: 1) as NSArray?).to(contain(1)) +#endif + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b")) + } + + failsWithErrorMessageForNil("expected to contain , got ") { + expect(nil as [String]?).to(contain("bar")) + } + failsWithErrorMessageForNil("expected to not contain , got ") { + expect(nil as [String]?).toNot(contain("b")) + } + } + + func testContainSubstring() { + expect("foo").to(contain("o")) + expect("foo").to(contain("oo")) + expect("foo").toNot(contain("z")) + expect("foo").toNot(contain("zz")) + + failsWithErrorMessage("expected to contain , got ") { + expect("foo").to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got ") { + expect("foo").toNot(contain("oo")) + } + } + + func testContainObjCSubstring() { + let str = NSString(string: "foo") + expect(str).to(contain(NSString(string: "o"))) + expect(str).to(contain(NSString(string: "oo"))) + expect(str).toNot(contain(NSString(string: "z"))) + expect(str).toNot(contain(NSString(string: "zz"))) + } + + func testVariadicArguments() { + expect([1, 2, 3]).to(contain(1, 2)) + expect([1, 2, 3]).toNot(contain(1, 4)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("a", "bar")) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b", "a")) + } + } + + func testCollectionArguments() { + expect([1, 2, 3]).to(contain([1, 2])) + expect([1, 2, 3]).toNot(contain([1, 4])) + + let collection = Array(1...10) + let slice = Array(collection[3...5]) + expect(collection).to(contain(slice)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain(["a", "bar"])) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain(["b", "a"])) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..30e3b26 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift @@ -0,0 +1,56 @@ +import Foundation +import XCTest +import Nimble + +final class EndWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EndWithTest) -> () throws -> Void)] { + return [ + ("testEndWithPositives", testEndWithPositives), + ("testEndWithNegatives", testEndWithNegatives), + ] + } + + func testEndWithPositives() { + expect([1, 2, 3]).to(endWith(3)) + expect([1, 2, 3]).toNot(endWith(2)) + expect([]).toNot(endWith(1)) + expect(["a", "b", "a"]).to(endWith("a")) + + expect("foobar").to(endWith("bar")) + expect("foobar").toNot(endWith("oo")) + expect("foobarfoo").to(endWith("foo")) + + expect(NSString(string: "foobar").description).to(endWith("bar")) + expect(NSString(string: "foobar").description).toNot(endWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(endWith("b")) + expect(NSArray(array: ["a", "b"])).toNot(endWith("a")) + expect(NSArray(array: [])).toNot(endWith("a")) + expect(NSArray(array: ["a", "b", "a"])).to(endWith("a")) +#endif + } + + func testEndWithNegatives() { + failsWithErrorMessageForNil("expected to end with <2>, got ") { + expect(nil as [Int]?).to(endWith(2)) + } + failsWithErrorMessageForNil("expected to not end with <2>, got ") { + expect(nil as [Int]?).toNot(endWith(2)) + } + + failsWithErrorMessage("expected to end with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(endWith(2)) + } + failsWithErrorMessage("expected to not end with <3>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(endWith(3)) + } + failsWithErrorMessage("expected to end with , got ") { + expect("batman").to(endWith("atm")) + } + failsWithErrorMessage("expected to not end with , got ") { + expect("batman").toNot(endWith("man")) + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..85be751 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift @@ -0,0 +1,276 @@ +import Foundation +import XCTest +import Nimble + +final class EqualTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EqualTest) -> () throws -> Void)] { + return [ + ("testEquality", testEquality), + ("testArrayEquality", testArrayEquality), + ("testSetEquality", testSetEquality), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ("testDictionaryEquality", testDictionaryEquality), + ("testDataEquality", testDataEquality), + ("testNSObjectEquality", testNSObjectEquality), + ("testOperatorEquality", testOperatorEquality), + ("testOperatorEqualityWithArrays", testOperatorEqualityWithArrays), + ("testOperatorEqualityWithDictionaries", testOperatorEqualityWithDictionaries), + ("testOptionalEquality", testOptionalEquality), + ("testArrayOfOptionalsEquality", testArrayOfOptionalsEquality), + ("testDictionariesWithDifferentSequences", testDictionariesWithDifferentSequences), + ] + } + + func testEquality() { + expect(1 as CInt).to(equal(1 as CInt)) + expect(1 as CInt).to(equal(1)) + expect(1).to(equal(1)) + expect("hello").to(equal("hello")) + expect("hello").toNot(equal("world")) + + expect { + 1 + }.to(equal(1)) + + failsWithErrorMessage("expected to equal , got ") { + expect("hello").to(equal("world")) + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello").toNot(equal("hello")) + } + } + + func testArrayEquality() { + expect([1, 2, 3]).to(equal([1, 2, 3])) + expect([1, 2, 3]).toNot(equal([1, 2])) + expect([1, 2, 3]).toNot(equal([1, 2, 4])) + + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + expect(array1).to(equal(array2)) + expect(array1).to(equal([1, 2, 3])) + expect(array1).toNot(equal([1, 2] as [Int])) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: [1, 2, 3])).to(equal(NSArray(array: [1, 2, 3]))) +#endif + + failsWithErrorMessage("expected to equal <[1, 2]>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(equal([1, 2])) + } + } + + func testSetEquality() { + expect(Set([1, 2])).to(equal(Set([1, 2]))) + expect(Set()).to(equal(Set())) + expect(Set()) == Set() + expect(Set([1, 2])) != Set() + + failsWithErrorMessageForNil("expected to equal <[1, 2]>, got ") { + expect(nil as Set?).to(equal(Set([1, 2]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3]>, missing <[1]>") { + expect(Set([2, 3])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[1, 2, 3, 4]>, extra <[4]>") { + expect(Set([1, 2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])) == Set([1, 2, 3]) + } + + failsWithErrorMessage("expected to not equal <[1, 2, 3]>, got <[1, 2, 3]>") { + expect(Set([1, 2, 3])) != Set([1, 2, 3]) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as String?).to(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect("foo").toNot(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect(nil as String?).toNot(equal("bar")) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int]?).to(equal(nil as [Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1]>, got ") { + expect(nil as [Int]?).toNot(equal([1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1]>") { + expect([1]).toNot(equal(nil as [Int]?)) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int: Int]?).to(equal(nil as [Int: Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1: 1]>, got ") { + expect(nil as [Int: Int]?).toNot(equal([1: 1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1: 1]>") { + expect([1: 1]).toNot(equal(nil as [Int: Int]?)) + } + + failsWithErrorMessageForNil("expected to not equal , got <1>") { + expect(1).toNot(equal(nil)) + } + } + + func testDictionaryEquality() { + expect(["foo": "bar"]).to(equal(["foo": "bar"])) + expect(["foo": "bar"]).toNot(equal(["foo": "baz"])) + + let actual = ["foo": "bar"] + let expected = ["foo": "bar"] + let unexpected = ["foo": "baz"] + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString)).to(equal(["foo": "bar"])) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString) as? [String: String]).to(equal(expected)) +#endif + } + + func testDataEquality() { + let actual = "foobar".data(using: .utf8) + let expected = "foobar".data(using: .utf8) + let unexpected = "foobarfoo".data(using: .utf8) + + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11) + let expectedErrorMessage = "expected to equal >, got >" + #else + let expectedErrorMessage = "expected to equal >," + + " got >" + #endif + + failsWithErrorMessage(expectedErrorMessage) { + expect(actual).to(equal(unexpected)) + } + } + + func testNSObjectEquality() { + expect(NSNumber(value: 1)).to(equal(NSNumber(value: 1))) + expect(NSNumber(value: 1)) == NSNumber(value: 1) + expect(NSNumber(value: 1)) != NSNumber(value: 2) + expect { NSNumber(value: 1) }.to(equal(1)) + } + + func testOperatorEquality() { + expect("foo") == "foo" + expect("foo") != "bar" + + failsWithErrorMessage("expected to equal , got ") { + expect("hello") == "world" + return + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello") != "hello" + return + } + } + + func testOperatorEqualityWithArrays() { + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + let array3: [Int] = [1, 2] + expect(array1) == array2 + expect(array1) != array3 + } + + func testOperatorEqualityWithDictionaries() { + let dict1 = ["foo": "bar"] + let dict2 = ["foo": "bar"] + let dict3 = ["foo": "baz"] + expect(dict1) == dict2 + expect(dict1) != dict3 + } + + func testOptionalEquality() { + expect(1 as CInt?).to(equal(1)) + expect(1 as CInt?).to(equal(1 as CInt?)) + } + + func testArrayOfOptionalsEquality() { + let array1: [Int?] = [1, nil, 3] + let array2: [Int?] = [nil, 2, 3] + let array3: [Int?] = [1, nil, 3] + + expect(array1).toNot(equal(array2)) + expect(array1).to(equal(array3)) + expect(array2).toNot(equal(array3)) + + let allNils1: [String?] = [nil, nil, nil, nil] + let allNils2: [String?] = [nil, nil, nil, nil] + let notReallyAllNils: [String?] = [nil, nil, nil, "turtles"] + + expect(allNils1).to(equal(allNils2)) + expect(allNils1).toNot(equal(notReallyAllNils)) + + let noNils1: [Int?] = [1, 2, 3, 4, 5] + let noNils2: [Int?] = [1, 3, 5, 7, 9] + + expect(noNils1).toNot(equal(noNils2)) + + failsWithErrorMessage("expected to equal <[Optional(1), nil]>, got <[nil, Optional(2)]>") { + let arrayOfOptionalInts: [Int?] = [nil, 2] + let anotherArrayOfOptionalInts: [Int?] = [1, nil] + expect(arrayOfOptionalInts).to(equal(anotherArrayOfOptionalInts)) + return + } + } + + func testDictionariesWithDifferentSequences() { + // see: https://github.com/Quick/Nimble/issues/61 + // these dictionaries generate different orderings of sequences. + let result = ["how": 1, "think": 1, "didnt": 2, "because": 1, + "interesting": 1, "always": 1, "right": 1, "such": 1, + "to": 3, "say": 1, "cool": 1, "you": 1, + "weather": 3, "be": 1, "went": 1, "was": 2, + "sometimes": 1, "and": 3, "mind": 1, "rain": 1, + "whole": 1, "everything": 1, "weather.": 1, "down": 1, + "kind": 1, "mood.": 1, "it": 2, "everyday": 1, "might": 1, + "more": 1, "have": 2, "person": 1, "could": 1, "tenth": 2, + "night": 1, "write": 1, "Youd": 1, "affects": 1, "of": 3, + "Who": 1, "us": 1, "an": 1, "I": 4, "my": 1, "much": 2, + "wrong.": 1, "peacefully.": 1, "amazing": 3, "would": 4, + "just": 1, "grade.": 1, "Its": 2, "The": 2, "had": 1, "that": 1, + "the": 5, "best": 1, "but": 1, "essay": 1, "for": 1, "summer": 2, + "your": 1, "grade": 1, "vary": 1, "pretty": 1, "at": 1, "rain.": 1, + "about": 1, "allow": 1, "thought": 1, "in": 1, "sleep": 1, "a": 1, + "hot": 1, "really": 1, "beach": 1, "life.": 1, "we": 1, "although": 1, ] + + let storyCount = ["The": 2, "summer": 2, "of": 3, "tenth": 2, "grade": 1, + "was": 2, "the": 5, "best": 1, "my": 1, "life.": 1, "I": 4, + "went": 1, "to": 3, "beach": 1, "everyday": 1, "and": 3, + "we": 1, "had": 1, "amazing": 3, "weather.": 1, "weather": 3, + "didnt": 2, "really": 1, "vary": 1, "much": 2, "always": 1, + "pretty": 1, "hot": 1, "although": 1, "sometimes": 1, "at": 1, + "night": 1, "it": 2, "would": 4, "rain.": 1, "mind": 1, "rain": 1, + "because": 1, "cool": 1, "everything": 1, "down": 1, "allow": 1, + "us": 1, "sleep": 1, "peacefully.": 1, "Its": 2, "how": 1, + "affects": 1, "your": 1, "mood.": 1, "Who": 1, "have": 2, + "thought": 1, "that": 1, "could": 1, "write": 1, "a": 1, + "whole": 1, "essay": 1, "just": 1, "about": 1, "in": 1, + "grade.": 1, "kind": 1, "right": 1, "Youd": 1, "think": 1, + "for": 1, "such": 1, "an": 1, "interesting": 1, "person": 1, + "might": 1, "more": 1, "say": 1, "but": 1, "you": 1, "be": 1, "wrong.": 1, ] + + expect(result).to(equal(storyCount)) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble + +final class HaveCountTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (HaveCountTest) -> () throws -> Void)] { + return [ + ("testHaveCountForArray", testHaveCountForArray), + ("testHaveCountForDictionary", testHaveCountForDictionary), + ("testHaveCountForSet", testHaveCountForSet), + ] + } + + func testHaveCountForArray() { + expect([1, 2, 3]).to(haveCount(3)) + expect([1, 2, 3]).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Array with count 1, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Array with count 3, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).notTo(haveCount(3)) + } + } + + func testHaveCountForDictionary() { + let dictionary = ["1": 1, "2": 2, "3": 3] + expect(dictionary).to(haveCount(3)) + expect(dictionary).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Dictionary with count 1, got 3\nActual Value: \(stringify(dictionary))") { + expect(dictionary).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Dictionary with count 3, got 3" + + "\nActual Value: \(stringify(dictionary))") { + expect(dictionary).notTo(haveCount(3)) + } + } + + func testHaveCountForSet() { + let set = Set([1, 2, 3]) + expect(set).to(haveCount(3)) + expect(set).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Set with count 1, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Set with count 3, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).notTo(haveCount(3)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..2d626f2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift @@ -0,0 +1,84 @@ +import Foundation +import XCTest +import Nimble + +final class MatchErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchErrorTest) -> () throws -> Void)] { + return [ + ("testMatchErrorPositive", testMatchErrorPositive), + ("testMatchErrorNegative", testMatchErrorNegative), + ("testMatchNSErrorPositive", testMatchNSErrorPositive), + ("testMatchNSErrorNegative", testMatchNSErrorNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ] + } + + func testMatchErrorPositive() { + expect(NimbleError.laugh).to(matchError(NimbleError.laugh)) + expect(NimbleError.laugh).to(matchError(NimbleError.self)) + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 1))) + + expect(NimbleError.laugh as Error).to(matchError(NimbleError.laugh)) + } + + func testMatchErrorNegative() { + expect(NimbleError.laugh).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh as Error).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh).toNot(matchError(EquatableError.self)) + expect(EquatableError.parameterized(x: 1)).toNot(matchError(EquatableError.parameterized(x: 2))) + } + + func testMatchNSErrorPositive() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 0, userInfo: nil) + + expect(error1).to(matchError(error2)) + } + + func testMatchNSErrorNegative() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + + expect(error1).toNot(matchError(error2)) + } + + func testMatchPositiveMessage() { + failsWithErrorMessage("expected to match error , got ") { + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 2))) + } + failsWithErrorMessage("expected to match error , got ") { + expect(NimbleError.laugh).to(matchError(NimbleError.cry)) + } + failsWithErrorMessage("expected to match error , got ") { + expect(CustomDebugStringConvertibleError.a).to(matchError(CustomDebugStringConvertibleError.b)) + } + + failsWithErrorMessage("expected to match error , got ") { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + expect(error1).to(matchError(error2)) + } + } + + func testMatchNegativeMessage() { + failsWithErrorMessage("expected to not match error , got ") { + expect(NimbleError.laugh).toNot(matchError(NimbleError.laugh)) + } + + failsWithErrorMessage("expected to match error from type , got ") { + expect(NimbleError.laugh).to(matchError(EquatableError.self)) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to match error , got no error") { + expect(nil as Error?).to(matchError(NimbleError.laugh)) + } + + failsWithErrorMessageForNil("expected to not match error , got no error") { + expect(nil as Error?).toNot(matchError(NimbleError.laugh)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift @@ -0,0 +1,46 @@ +import XCTest +import Nimble + +final class MatchTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchTest) -> () throws -> Void)] { + return [ + ("testMatchPositive", testMatchPositive), + ("testMatchNegative", testMatchNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testMatchNils", testMatchNils), + ] + } + + func testMatchPositive() { + expect("11:14").to(match("\\d{2}:\\d{2}")) + } + + func testMatchNegative() { + expect("hello").toNot(match("\\d{2}:\\d{2}")) + } + + func testMatchPositiveMessage() { + let message = "expected to match <\\d{2}:\\d{2}>, got " + failsWithErrorMessage(message) { + expect("hello").to(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNegativeMessage() { + let message = "expected to not match <\\d{2}:\\d{2}>, got <11:14>" + failsWithErrorMessage(message) { + expect("11:14").toNot(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNils() { + failsWithErrorMessageForNil("expected to match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).to(match("\\d{2}:\\d{2}")) + } + + failsWithErrorMessageForNil("expected to not match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).toNot(match("\\d{2}:\\d{2}")) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..ac7f9ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift @@ -0,0 +1,91 @@ +import XCTest +import Nimble +import Foundation + +final class PostNotificationTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PostNotificationTest) -> () throws -> Void)] { + return [ + ("testPassesWhenNoNotificationsArePosted", testPassesWhenNoNotificationsArePosted), + ("testPassesWhenExpectedNotificationIsPosted", testPassesWhenExpectedNotificationIsPosted), + ("testPassesWhenAllExpectedNotificationsArePosted", testPassesWhenAllExpectedNotificationsArePosted), + ("testFailsWhenNoNotificationsArePosted", testFailsWhenNoNotificationsArePosted), + ("testFailsWhenNotificationWithWrongNameIsPosted", testFailsWhenNotificationWithWrongNameIsPosted), + ("testFailsWhenNotificationWithWrongObjectIsPosted", testFailsWhenNotificationWithWrongObjectIsPosted), + ("testPassesWhenExpectedNotificationEventuallyIsPosted", testPassesWhenExpectedNotificationEventuallyIsPosted), + ] + } + + let notificationCenter = NotificationCenter() + + func testPassesWhenNoNotificationsArePosted() { + expect { + // no notifications here! + return nil + }.to(postNotifications(beEmpty(), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenExpectedNotificationIsPosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + self.notificationCenter.post(testNotification) + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenAllExpectedNotificationsArePosted() { + let foo = NSNumber(value: 1) + let bar = NSNumber(value: 2) + let n1 = Notification(name: Notification.Name("Foo"), object: foo) + let n2 = Notification(name: Notification.Name("Bar"), object: bar) + expect { + self.notificationCenter.post(n1) + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1, n2]), fromNotificationCenter: notificationCenter)) + } + + func testFailsWhenNoNotificationsArePosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + failsWithErrorMessage("expected to equal <[\(testNotification)]>, got no notifications") { + expect { + // no notifications here! + return nil + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongNameIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: Notification.Name(n1.name.rawValue + "a"), object: nil) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongObjectIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: n1.name, object: NSObject()) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testPassesWhenExpectedNotificationEventuallyIsPosted() { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + deferToMainQueue { + self.notificationCenter.post(testNotification) + } + return nil + }.toEventually(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + #else + print("\(#function) is missing because toEventually is not implement on this platform") + #endif + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..f62f633 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class RaisesExceptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (RaisesExceptionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testNegativeMatchesDoNotCallClosureWithoutException", testNegativeMatchesDoNotCallClosureWithoutException), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + var anException = NSException(name: NSExceptionName("laugh"), reason: "Lulz", userInfo: ["key": "value"]) + + func testPositiveMatches() { + expect { self.anException.raise() }.to(raiseException()) + expect { self.anException.raise() }.to(raiseException(named: "laugh")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + + func testPositiveMatchesWithClosures() { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName("laugh"))) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("df")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + failsWithErrorMessage("expected to raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "foo")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "bar")) + } + + failsWithErrorMessage( + "expected to raise exception with name with reason with userInfo <{k = v;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["k": "v"])) + } + + failsWithErrorMessage("expected to raise any exception, got no exception") { + expect { self.anException }.to(raiseException()) + } + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + failsWithErrorMessage("expected to raise exception with name with reason , got no exception") { + expect { self.anException }.to(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "bar", reason: "Lulz")) + } + failsWithErrorMessage("expected to not raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh")) + } + failsWithErrorMessage("expected to not raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to not raise exception with name with reason with userInfo <{key = value;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutException() { + failsWithErrorMessage("expected to raise exception that satisfies block, got no exception") { + expect { self.anException }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName(rawValue: "foo"))) + }) + } + + failsWithErrorMessage("expected to raise exception with name that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "ha") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason with userInfo <{}> that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + } + + func testNegativeMatchesWithClosure() { + failsWithErrorMessage("expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + let innerFailureMessage = "expected to begin with , got " + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "wrong") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift new file mode 100644 index 0000000..42ed892 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift @@ -0,0 +1,57 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAllOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAllOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAllOf", testSatisfyAllOf), + ("testOperatorAnd", testOperatorAnd), + ] + } + + func testSatisfyAllOf() { + expect(2).to(satisfyAllOf(equal(2), beLessThan(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAllOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAllOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAllOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").to(satisfyAllOf(contain("e"), beginWith("tur"))) + expect(82.0).to(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(82.00001))) + expect(false).toNot(satisfyAllOf(beTrue(), beFalse())) + expect(true).toNot(satisfyAllOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2") { + expect(2).to(satisfyAllOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match all of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, and {equal <[5, 6, 7]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAllOf(allPass("be less than 4", {$0 < 4}), equal([5, 6, 7]))) + } + failsWithErrorMessage( + "expected to not match all of: {be false}, got false") { + expect(false).toNot(satisfyAllOf(beFalse())) + } + failsWithErrorMessage( + "expected to not match all of: {be greater than <10.5>}, and {be less than <100.75>}, and {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorAnd() { + expect(2).to(equal(2) && beLessThan(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).to(beLessThan(3) && beGreaterThan(1)) +#else + expect(2 as NSNumber).to(beLessThan(3 as NSNumber) && beGreaterThan(1 as NSNumber)) +#endif + expect("turtle").to(contain("t") && endWith("tle")) + expect(82.0).to(beGreaterThan(10.5) && beLessThan(100.75)) + expect(false).to(beFalsy() && beFalse()) + expect(false).toNot(beTrue() && beFalse()) + expect(true).toNot(beTruthy() && beFalsy()) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAnyOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAnyOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAnyOf", testSatisfyAnyOf), + ("testOperatorOr", testOperatorOr), + ] + } + + func testSatisfyAnyOf() { + expect(2).to(satisfyAnyOf(equal(2), equal(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAnyOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAnyOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAnyOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").toNot(satisfyAnyOf(contain("a"), endWith("magic"))) + expect(82.0).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + expect(false).to(satisfyAnyOf(beTrue(), beFalse())) + expect(true).to(satisfyAnyOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2") { + expect(2).to(satisfyAnyOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match one of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, or {equal <[1, 2, 3, 4]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAnyOf(allPass("be less than 4", {$0 < 4}), equal([1, 2, 3, 4]))) + } + failsWithErrorMessage( + "expected to match one of: {be true}, got false") { + expect(false).to(satisfyAnyOf(beTrue())) + } + failsWithErrorMessage( + "expected to not match one of: {be less than <10.5>}, or {be greater than <100.75>}, or {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorOr() { + expect(2).to(equal(2) || equal(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(equal(3) || equal("turtles")) +#else + expect(2 as NSNumber).toNot(equal(3 as NSNumber) || equal("turtles" as NSString)) +#endif + expect("turtle").toNot(contain("a") || endWith("magic")) + expect(82.0).toNot(beLessThan(10.5) || beGreaterThan(100.75)) + expect(false).to(beTrue() || beFalse()) + expect(true).to(beTruthy() || beFalsy()) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..68086e0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,62 @@ +import Foundation +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class ThrowAssertionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowAssertionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testErrorThrown", testErrorThrown), + ("testPostAssertionCodeNotRun", testPostAssertionCodeNotRun), + ("testNegativeMatch", testNegativeMatch), + ("testPositiveMessage", testPositiveMessage), + ("testNegativeMessage", testNegativeMessage), + ] + } + + func testPositiveMatch() { + expect { () -> Void in fatalError() }.to(throwAssertion()) + } + + func testErrorThrown() { + expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + } + + func testPostAssertionCodeNotRun() { + var reachedPoint1 = false + var reachedPoint2 = false + + expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true + }.to(throwAssertion()) + + expect(reachedPoint1) == true + expect(reachedPoint2) == false + } + + func testNegativeMatch() { + var reachedPoint1 = false + + expect { reachedPoint1 = true }.toNot(throwAssertion()) + + expect(reachedPoint1) == true + } + + func testPositiveMessage() { + failsWithErrorMessage("expected to throw an assertion") { + expect { () -> Void? in return }.to(throwAssertion()) + } + } + + func testNegativeMessage() { + failsWithErrorMessage("expected to not throw an assertion") { + expect { () -> Void in fatalError() }.toNot(throwAssertion()) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..f11c8c5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift @@ -0,0 +1,155 @@ +import XCTest +import Nimble + +enum NimbleError: Error { + case laugh + case cry +} + +enum EquatableError: Error { + case parameterized(x: Int) +} + +extension EquatableError: Equatable { +} + +func == (lhs: EquatableError, rhs: EquatableError) -> Bool { + switch (lhs, rhs) { + case (.parameterized(let l), .parameterized(let r)): + return l == r + } +} + +enum CustomDebugStringConvertibleError: Error { + case a + case b +} + +extension CustomDebugStringConvertibleError: CustomDebugStringConvertible { + var debugDescription: String { + return "code=\(_code)" + } +} + +final class ThrowErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowErrorTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testPositiveNegatedMatches", testPositiveNegatedMatches), + ("testNegativeNegatedMatches", testNegativeNegatedMatches), + ("testNegativeMatchesDoNotCallClosureWithoutError", testNegativeMatchesDoNotCallClosureWithoutError), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + func testPositiveMatches() { + expect { throw NimbleError.laugh }.to(throwError()) + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh)) + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self)) + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 1))) + expect { throw EquatableError.parameterized(x: 1) }.toNot(throwError(EquatableError.parameterized(x: 2))) + } + + func testPositiveMatchesWithClosures() { + // Generic typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { error in + guard case EquatableError.parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Explicit typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { (error: EquatableError) in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over errorType argument + expect { throw EquatableError.parameterized(x: 42) }.to(throwError(errorType: EquatableError.self) { error in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).to(beginWith("Nim")) + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Different case + failsWithErrorMessage("expected to throw error , got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry)) + } + // Different case with closure + failsWithErrorMessage("expected to throw error that satisfies block, got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry) { _ in return }) + } + // Different case, implementing CustomDebugStringConvertible + failsWithErrorMessage("expected to throw error , got ") { + expect { throw CustomDebugStringConvertibleError.a }.to(throwError(CustomDebugStringConvertibleError.b)) + } + } + + func testPositiveNegatedMatches() { + // No error at all + expect { return }.toNot(throwError()) + // Different case + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.cry)) + } + + func testNegativeNegatedMatches() { + // No error at all + failsWithErrorMessage("expected to not throw any error, got ") { + expect { throw NimbleError.laugh }.toNot(throwError()) + } + // Different error + failsWithErrorMessage("expected to not throw error , got ") { + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.laugh)) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutError() { + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError { _ in + fail() + }) + } + + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError(NimbleError.laugh) { _ in + fail() + }) + } + } + + func testNegativeMatchesWithClosure() { + let moduleName = "NimbleTests" + let innerFailureMessage = "expected to equal , got <\(moduleName).NimbleError>" + let closure = { (error: Error) in + expect(error._domain).to(equal("foo")) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error from type that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self, closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh, closure: closure)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift new file mode 100644 index 0000000..dde999a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift @@ -0,0 +1,36 @@ +import XCTest +import Nimble + +final class ToSucceedTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ToSucceedTest) -> () throws -> Void)] { + return [ + ("testToSucceed", testToSucceed), + ] + } + + func testToSucceed() { + expect({ + return .succeeded + }).to(succeed()) + + expect({ + return .failed(reason: "") + }).toNot(succeed()) + + failsWithErrorMessageForNil("expected a closure, got ") { + expect(nil as (() -> ToSucceedResult)?).to(succeed()) + } + + failsWithErrorMessage("expected to succeed, got because ") { + expect({ + .failed(reason: "something went wrong") + }).to(succeed()) + } + + failsWithErrorMessage("expected to not succeed, got ") { + expect({ + return .succeeded + }).toNot(succeed()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift new file mode 100644 index 0000000..ce8181b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift @@ -0,0 +1,128 @@ +import Foundation +import XCTest +import Nimble + +final class SynchronousTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SynchronousTest) -> () throws -> Void)] { + return [ + ("testFailAlwaysFails", testFailAlwaysFails), + ("testUnexpectedErrorsThrownFails", testUnexpectedErrorsThrownFails), + ("testToMatchesIfMatcherReturnsTrue", testToMatchesIfMatcherReturnsTrue), + ("testToProvidesActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToMatchAgainstLazyProperties", testToMatchAgainstLazyProperties), + ("testToNotMatchesIfMatcherReturnsTrue", testToNotMatchesIfMatcherReturnsTrue), + ("testToNotProvidesActualValueExpression", testToNotProvidesActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpression", testToNotProvidesAMemoizedActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToNotNegativeMatches", testToNotNegativeMatches), + ("testNotToMatchesLikeToNot", testNotToMatchesLikeToNot), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testFailAlwaysFails() { + failsWithErrorMessage("My error message") { + fail("My error message") + } + failsWithErrorMessage("fail() always fails") { + fail() + } + } + + func testUnexpectedErrorsThrownFails() { + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.to(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toNot(equal(1)) + } + } + + func testToMatchesIfMatcherReturnsTrue() { + expect(1).to(MatcherFunc { _, _ in true }) + expect {1}.to(MatcherFunc { _, _ in true }) + } + + func testToProvidesActualValueExpression() { + var value: Int? + expect(1).to(MatcherFunc { expr, _ in value = try expr.evaluate(); return true }) + expect(value).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToMatchAgainstLazyProperties() { + expect(ObjectWithLazyProperty().value).to(equal("hello")) + expect(ObjectWithLazyProperty().value).toNot(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).to(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).toNot(equal("hello")) + } + + // repeated tests from to() for toNot() + func testToNotMatchesIfMatcherReturnsTrue() { + expect(1).toNot(MatcherFunc { _, _ in false }) + expect {1}.toNot(MatcherFunc { _, _ in false }) + } + + func testToNotProvidesActualValueExpression() { + var value: Int? + expect(1).toNot(MatcherFunc { expr, _ in value = try expr.evaluate(); return false }) + expect(value).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotNegativeMatches() { + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }) + } + } + + func testNotToMatchesLikeToNot() { + expect(1).notTo(MatcherFunc { _, _ in false }) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift @@ -0,0 +1,64 @@ +import XCTest +import Nimble + +final class UserDescriptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (UserDescriptionTest) -> () throws -> Void)] { + return [ + ("testToMatcher_CustomFailureMessage", testToMatcher_CustomFailureMessage), + ("testNotToMatcher_CustomFailureMessage", testNotToMatcher_CustomFailureMessage), + ("testToNotMatcher_CustomFailureMessage", testToNotMatcher_CustomFailureMessage), + ("testToEventuallyMatch_CustomFailureMessage", testToEventuallyMatch_CustomFailureMessage), + ("testToEventuallyNotMatch_CustomFailureMessage", testToEventuallyNotMatch_CustomFailureMessage), + ("testToNotEventuallyMatch_CustomFailureMessage", testToNotEventuallyMatch_CustomFailureMessage), + ] + } + + func testToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }, description: "These aren't equal!") + } + } + + func testNotToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).notTo(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToNotMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't eventually equal!\n" + + "expected to eventually equal <1>, got <0>") { + expect { 0 }.toEventually(equal(1), description: "These aren't eventually equal!") + } + } + + func testToEventuallyNotMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + + func testToNotEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h @@ -0,0 +1,15 @@ +@import Nimble; +#import "NimbleTests-Swift.h" + +// Use this when you want to verify the failure message for when an expectation fails +#define expectFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessage:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + +#define expectFailureMessages(MSGS, BLOCK) \ +[NimbleHelper expectFailureMessages:(MSGS) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + + +// Use this when you want to verify the failure message with the nil message postfixed +// to it: " (use beNil() to match nils)" +#define expectNilFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessageForNil:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..4bdc021 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m @@ -0,0 +1,38 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAllPassTest : XCTestCase + +@end + +@implementation ObjCAllPassTest + +- (void)testPositiveMatches { + expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); + expect(@[@1, @2, @3,@4]).toNot(allPass(beGreaterThan(@5))); + + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).to(allPass(beLessThan(@5))); + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).toNot(allPass(beGreaterThan(@5))); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to all be less than <3>, but failed first at element" + " <3> in <[1, 2, 3, 4]>", ^{ + expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@3))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect(@[@1, @2, @3, @4]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect([NSSet setWithArray:@[@1, @2, @3, @4]]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).to(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).toNot(allPass(beLessThan(@5))); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m @@ -0,0 +1,55 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAsyncTest : XCTestCase + +@end + +@implementation ObjCAsyncTest + +- (void)testAsync { + __block id obj = @1; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = nil; + }); + expect(obj).toEventually(beNil()); +} + + +- (void)testAsyncWithCustomTimeout { + __block id obj = nil; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = @1; + }); + expect(obj).withTimeout(5).toEventuallyNot(beNil()); +} + +- (void)testAsyncCallback { + waitUntil(^(void (^done)(void)){ + done(); + }); + + expectFailureMessage(@"Waited more than 1.0 second", ^{ + waitUntil(^(void (^done)(void)){ /* ... */ }); + }); + + expectFailureMessage(@"Waited more than 0.01 seconds", ^{ + waitUntilTimeout(0.01, ^(void (^done)(void)){ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [NSThread sleepForTimeInterval:0.1]; + done(); + }); + }); + }); + + expectFailureMessage(@"expected to equal , got ", ^{ + waitUntil(^(void (^done)(void)){ + [NSThread sleepForTimeInterval:0.1]; + expect(@"hello").to(equal(@"goodbye")); + done(); + }); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeAnInstanceOfTest : XCTestCase +@end + +@implementation ObjCBeAnInstanceOfTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beAnInstanceOf([NSNull class])); + expect(@1).toNot(beAnInstanceOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be an instance of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAnInstanceOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAnInstanceOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be an instance of NSNull, got ", ^{ + expect(nil).to(beAnInstanceOf([NSNull class])); + }); + + expectNilFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect(nil).toNot(beAnInstanceOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeCloseToTest : XCTestCase + +@end + +@implementation ObjCBeCloseToTest + +- (void)testPositiveMatches { + expect(@1.2).to(beCloseTo(@1.2001)); + expect(@1.2).to(beCloseTo(@2).within(10)); + expect(@2).toNot(beCloseTo(@1)); + expect(@1.00001).toNot(beCloseTo(@1).within(0.00000001)); + + expect(1.2).to(beCloseTo(1.2001)); + expect(1.2).to(beCloseTo(2).within(10)); + expect(2).toNot(beCloseTo(1)); + expect(1.00001).toNot(beCloseTo(1).within(0.00000001)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(@1).to(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(@(0.0001)).toNot(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(1).to(beCloseTo(0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(0.0001).toNot(beCloseTo(0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be close to <0> (within 0.001), got ", ^{ + expect(nil).to(beCloseTo(@0)); + }); + expectNilFailureMessage(@"expected to not be close to <0> (within 0.001), got ", ^{ + expect(nil).toNot(beCloseTo(@0)); + }); +} + + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..5e803cb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m @@ -0,0 +1,89 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeEmptyTest : XCTestCase +@end + +@implementation ObjCBeEmptyTest + +- (void)testPositiveMatches { + expect(@[]).to(beEmpty()); + expect(@"").to(beEmpty()); + expect(@{}).to(beEmpty()); + expect([NSSet set]).to(beEmpty()); + expect([NSIndexSet indexSet]).to(beEmpty()); + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]).to(beEmpty()); + + expect(@[@1, @2]).toNot(beEmpty()); + expect(@"a").toNot(beEmpty()); + expect(@{@"key": @"value"}).toNot(beEmpty()); + expect([NSSet setWithObject:@1]).toNot(beEmpty()); + expect([NSIndexSet indexSetWithIndex:1]).toNot(beEmpty()); + + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + expect(table).toNot(beEmpty()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be empty, got ", ^{ + expect(@"foo").to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect(@[@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{key = value;}>", ^{ + expect(@{@"key": @"value"}).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{(1)}>", ^{ + expect([NSSet setWithObject:@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect([NSIndexSet indexSetWithIndex:1]).to(beEmpty()); + }); + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + NSString *tableString = [[table description] stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be empty, got <%@>", tableString]), ^{ + expect(table).to(beEmpty()); + }); + + expectFailureMessage(@"expected to not be empty, got <>", ^{ + expect(@"").toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect(@[]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{}>", ^{ + expect(@{}).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{()}>", ^{ + expect([NSSet set]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect([NSIndexSet indexSet]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got ", ^{ + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]).toNot(beEmpty()); + }); +} + +- (void)testItDoesNotMatchNil { + expectNilFailureMessage(@"expected to be empty, got ", ^{ + expect(nil).to(beEmpty()); + }); + expectNilFailureMessage(@"expected to not be empty, got ", ^{ + expect(nil).toNot(beEmpty()); + }); +} + +- (void)testItReportsTypesItMatchesAgainst { + expectFailureMessage(@"expected to be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).to(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).toNot(beEmpty()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m @@ -0,0 +1,46 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalseTest : XCTestCase + +@end + +@implementation ObjCBeFalseTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalse()); + expect(@YES).toNot(beFalse()); + + expect(false).to(beFalse()); + expect(true).toNot(beFalse()); + + expect(NO).to(beFalse()); + expect(YES).toNot(beFalse()); + + expect(10).toNot(beFalse()); +} + +- (void)testNegativeMatches { + expectNilFailureMessage(@"expected to be false, got ", ^{ + expect(nil).to(beFalse()); + }); + expectNilFailureMessage(@"expected to not be false, got ", ^{ + expect(nil).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(true).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(false).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(YES).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(NO).toNot(beFalse()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m @@ -0,0 +1,58 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalsyTest : XCTestCase + +@end + +@implementation ObjCBeFalsyTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalsy()); + expect(@YES).toNot(beFalsy()); + expect(nil).to(beFalsy()); + + expect(true).toNot(beFalsy()); + expect(false).to(beFalsy()); + + expect(YES).toNot(beFalsy()); + expect(NO).to(beFalsy()); + + expect(10).toNot(beFalsy()); + expect(0).to(beFalsy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to not be falsy, got ", ^{ + expect(nil).toNot(beFalsy()); + }); + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(@1).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(@NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(true).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(false).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(YES).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <10>", ^{ + expect(10).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(0).toNot(beFalsy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..28862ba --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m @@ -0,0 +1,44 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThanOrEqualTo(@2)); + expect(@2).toNot(beGreaterThanOrEqualTo(@3)); + expect(2).to(beGreaterThanOrEqualTo(0)); + expect(2).to(beGreaterThanOrEqualTo(2)); + expect(2).toNot(beGreaterThanOrEqualTo(3)); + expect(2.5).to(beGreaterThanOrEqualTo(2)); + expect(2.5).to(beGreaterThanOrEqualTo(2.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThanOrEqualTo(@0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThanOrEqualTo(@(1))); + }); + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(-1).to(beGreaterThanOrEqualTo(0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(2).toNot(beGreaterThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than or equal to <-1>, got ", ^{ + expect(nil).to(beGreaterThanOrEqualTo(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than or equal to <1>, got ", ^{ + expect(nil).toNot(beGreaterThanOrEqualTo(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..5a57d54 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThan(@1)); + expect(@2).toNot(beGreaterThan(@2)); + expect(@2).to(beGreaterThan(0)); + expect(@2).toNot(beGreaterThan(2)); + expect(2.5).to(beGreaterThan(1.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThan(@(0))); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThan(@(1))); + }); + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(-1).to(beGreaterThan(0)); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(2).toNot(beGreaterThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than <-1>, got ", ^{ + expect(nil).to(beGreaterThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than <1>, got ", ^{ + expect(nil).toNot(beGreaterThan(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m @@ -0,0 +1,68 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeIdenticalToTest : XCTestCase + +@end + +@implementation ObjCBeIdenticalToTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beIdenticalTo([NSNull null])); + expect(@2).toNot(beIdenticalTo(@3)); +} + +- (void)testNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(beIdenticalTo(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(beIdenticalTo(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testAliasPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(be([NSNull null])); + expect(@2).toNot(be(@3)); +} + +- (void)testAliasNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(be(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(be(obj)); + }); +} + +- (void)testAliasNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(be(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(be(obj)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeKindOfTest : XCTestCase + +@end + +@implementation ObjCBeKindOfTest + +- (void)testPositiveMatches { + NSMutableArray *array = [NSMutableArray array]; + expect(array).to(beAKindOf([NSArray class])); + expect(@1).toNot(beAKindOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be a kind of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAKindOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAKindOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be a kind of NSNull, got ", ^{ + expect(nil).to(beAKindOf([NSNull class])); + }); + expectNilFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect(nil).toNot(beAKindOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m @@ -0,0 +1,43 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeLessThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThanOrEqualTo(@2)); + expect(@2).toNot(beLessThanOrEqualTo(@1)); + expect(2).to(beLessThanOrEqualTo(2)); + expect(2).toNot(beLessThanOrEqualTo(1)); + expect(2).toNot(beLessThanOrEqualTo(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(@2).to(beLessThanOrEqualTo(@1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(@1).toNot(beLessThanOrEqualTo(@1)); + }); + + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(2).to(beLessThanOrEqualTo(1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(1).toNot(beLessThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than or equal to <1>, got ", ^{ + expect(nil).to(beLessThanOrEqualTo(@1)); + }); + expectNilFailureMessage(@"expected to not be less than or equal to <-1>, got ", ^{ + expect(nil).toNot(beLessThanOrEqualTo(@(-1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..9750641 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanTest : XCTestCase + +@end + +@implementation ObjCBeLessThanTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThan(@3)); + expect(@2).toNot(beLessThan(@2)); + expect(2).to(beLessThan(3)); + expect(2).toNot(beLessThan(2)); + expect(2).toNot(beLessThan(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(@(1)).to(beLessThan(@0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(@0).toNot(beLessThan(@1)); + }); + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(1).to(beLessThan(0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(0).toNot(beLessThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than <-1>, got ", ^{ + expect(nil).to(beLessThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be less than <1>, got ", ^{ + expect(nil).toNot(beLessThan(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m @@ -0,0 +1,24 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeNilTest : XCTestCase + +@end + +@implementation ObjCBeNilTest + +- (void)testPositiveMatches { + expect(nil).to(beNil()); + expect(@NO).toNot(beNil()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be nil, got <1>", ^{ + expect(@1).to(beNil()); + }); + expectFailureMessage(@"expected to not be nil, got ", ^{ + expect(nil).toNot(beNil()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTrueTest : XCTestCase + +@end + +@implementation ObjCBeTrueTest + +- (void)testPositiveMatches { + expect(@YES).to(beTrue()); + expect(@NO).toNot(beTrue()); + expect(nil).toNot(beTrue()); + + expect(true).to(beTrue()); + expect(false).toNot(beTrue()); + + expect(YES).to(beTrue()); + expect(NO).toNot(beTrue()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(@NO).to(beTrue()); + }); + expectFailureMessage(@"expected to be true, got ", ^{ + expect(nil).to(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(false).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(true).toNot(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(NO).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(YES).toNot(beTrue()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m @@ -0,0 +1,55 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTruthyTest : XCTestCase + +@end + +@implementation ObjCBeTruthyTest + +- (void)testPositiveMatches { + expect(@YES).to(beTruthy()); + expect(@NO).toNot(beTruthy()); + expect(nil).toNot(beTruthy()); + + expect(true).to(beTruthy()); + expect(false).toNot(beTruthy()); + + expect(YES).to(beTruthy()); + expect(NO).toNot(beTruthy()); + + expect(10).to(beTruthy()); + expect(0).toNot(beTruthy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be truthy, got ", ^{ + expect(nil).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(@1).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(@NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(false).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(true).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(YES).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <10>", ^{ + expect(10).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(0).to(beTruthy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeginWithTest : XCTestCase + +@end + +@implementation ObjCBeginWithTest + +- (void)testPositiveMatches { + expect(@"hello world!").to(beginWith(@"hello")); + expect(@"hello world!").toNot(beginWith(@"world")); + + NSArray *array = @[@1, @2]; + expect(array).to(beginWith(@1)); + expect(array).toNot(beginWith(@2)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to begin with , got ", ^{ + expect(@"foo").to(beginWith(@"bar")); + }); + expectFailureMessage(@"expected to not begin with , got ", ^{ + expect(@"foo").toNot(beginWith(@"foo")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to begin with <1>, got ", ^{ + expect(nil).to(beginWith(@1)); + }); + expectNilFailureMessage(@"expected to not begin with <1>, got ", ^{ + expect(nil).toNot(beginWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m @@ -0,0 +1,64 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainElementSatisfyingTest : XCTestCase + +@end + +@implementation ObjCContainElementSatisfyingTest + +- (void)testPassingMatches { + NSArray *orderIndifferentArray = @[@1, @2, @3]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + orderIndifferentArray = @[@3, @1, @2]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + NSSet *orderIndifferentSet = [NSSet setWithObjects:@"turtle test", @"turtle assessment", nil]; + expect(orderIndifferentSet).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"turtle assessment"]; + })); +} + +- (void)testFailingMatches { + expectFailureMessage(@"expected to find object in collection that satisfies predicate", ^{ + expect(@[@1]).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((nil)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((@3)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); +} + +- (void)testNegativeCases { + NSArray *orderIndifferentArray = @[@"puppies", @"kittens", @"turtles"]; + expect(orderIndifferentArray).toNot(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"armadillos"]; + })); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..8b954fe --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m @@ -0,0 +1,67 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainTest : XCTestCase + +@end + +@implementation ObjCContainTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1)); + expect(array).toNot(contain(@"HI")); + expect(@"String").to(contain(@"Str")); + expect(@"Other").toNot(contain(@"Str")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to contain <3>, got <(1, 2)>", ^{ + expect((@[@1, @2])).to(contain(@3)); + }); + expectFailureMessage(@"expected to not contain <2>, got <(1, 2)>", ^{ + expect((@[@1, @2])).toNot(contain(@2)); + }); + + expectFailureMessage(@"expected to contain , got ", ^{ + expect(@"la").to(contain(@"hi")); + }); + expectFailureMessage(@"expected to not contain , got ", ^{ + expect(@"hihihi").toNot(contain(@"hi")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to contain <3>, got ", ^{ + expect(nil).to(contain(@3)); + }); + expectNilFailureMessage(@"expected to not contain <3>, got ", ^{ + expect(nil).toNot(contain(@3)); + }); + + expectNilFailureMessage(@"expected to contain , got ", ^{ + expect(nil).to(contain(@"hi")); + }); + expectNilFailureMessage(@"expected to not contain , got ", ^{ + expect(nil).toNot(contain(@"hi")); + }); +} + +- (void)testVariadicArguments { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1, @2)); + expect(array).toNot(contain(@"HI", @"whale")); + expect(@"String").to(contain(@"Str", @"ng")); + expect(@"Other").toNot(contain(@"Str", @"Oth")); + + + expectFailureMessage(@"expected to contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).to(contain(@"a", @"bar")); + }); + + expectFailureMessage(@"expected to not contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).toNot(contain(@"a", @"b")); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEndWithTest : XCTestCase + +@end + +@implementation ObjCEndWithTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(@"hello world!").to(endWith(@"world!")); + expect(@"hello world!").toNot(endWith(@"hello")); + expect(array).to(endWith(@2)); + expect(array).toNot(endWith(@1)); + expect(@1).toNot(contain(@"foo")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to end with , got ", ^{ + expect(@"hello world!").to(endWith(@"?")); + }); + expectFailureMessage(@"expected to not end with , got ", ^{ + expect(@"hello world!").toNot(endWith(@"!")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to end with <1>, got ", ^{ + expect(nil).to(endWith(@1)); + }); + expectNilFailureMessage(@"expected to not end with <1>, got ", ^{ + expect(nil).toNot(endWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..9d1361e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m @@ -0,0 +1,94 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEqualTest : XCTestCase + +@end + +@implementation ObjCEqualTest + +- (void)testPositiveMatches { + expect(@1).to(equal(@1)); + expect(@1).toNot(equal(@2)); + expect(@1).notTo(equal(@2)); + expect(@"hello").to(equal(@"hello")); + expect("hello").to(equal("hello")); + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 10))); + expect(NSMakeRange(0, 10)).toNot(equal(NSMakeRange(0, 5))); + expect((NSInteger)1).to(equal((NSInteger)1)); + expect((NSInteger)1).toNot(equal((NSInteger)2)); + expect((NSUInteger)1).to(equal((NSUInteger)1)); + expect((NSUInteger)1).toNot(equal((NSUInteger)2)); + expect(0).to(equal(0)); + expect(1).to(equal(1)); + expect(1).toNot(equal(2)); + expect(1.0).to(equal(1.0)); // Note: not recommended, use beCloseTo() instead + expect(1.0).toNot(equal(2.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).to(equal((float)1.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).toNot(equal((float)2.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).to(equal((double)1.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).toNot(equal((double)2.0)); // Note: not recommended, use beCloseTo() instead + expect((long long)1).to(equal((long long)1)); + expect((long long)1).toNot(equal((long long)2)); + expect((unsigned long long)1).to(equal((unsigned long long)1)); + expect((unsigned long long)1).toNot(equal((unsigned long long)2)); +} + +- (void)testNimbleCurrentlyBoxesNumbersWhichAllowsImplicitTypeConversions { + expect(1).to(equal(1.0)); + expect((long long)1).to(equal((unsigned long long)1)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(@1).to(equal(@2)); + }); + expectFailureMessage(@"expected to not equal <1>, got <1>", ^{ + expect(@1).toNot(equal(@1)); + }); + expectFailureMessage(@"expected to not equal , got ", ^{ + expect("bar").toNot(equal("bar")); + }); + expectFailureMessage(@"expected to equal , got ", ^{ + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 5))); + }); + + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSInteger)1).to(equal((NSInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSUInteger)1).to(equal((NSUInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1).to(equal(2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1.0).to(equal(2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((float)1.0).to(equal((float)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((double)1.0).to(equal((double)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((long long)1.0).to(equal((long long)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((unsigned long long)1.0).to(equal((unsigned long long)2.0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(NULL).to(equal(NULL)); + }); + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(nil).to(equal(nil)); + }); + expectNilFailureMessage(@"expected to not equal , got ", ^{ + expect(nil).toNot(equal(nil)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m @@ -0,0 +1,174 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCHaveCountTest : XCTestCase + +@end + +@implementation ObjCHaveCountTest + +- (void)testHaveCountForNSArray { + expect(@[@1, @2, @3]).to(haveCount(@3)); + expect(@[@1, @2, @3]).notTo(haveCount(@1)); + + expect(@[]).to(haveCount(@0)); + expect(@[@1]).notTo(haveCount(@0)); + + expect(@[@1, @2, @3]).to(haveCount(3)); + expect(@[@1, @2, @3]).notTo(haveCount(1)); + + expect(@[]).to(haveCount(0)); + expect(@[@1]).notTo(haveCount(0)); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSDictionary { + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@1)); + + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSHashtable { + NSHashTable *const table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + [table addObject:@2]; + [table addObject:@3]; + + expect(table).to(haveCount(@3)); + expect(table).notTo(haveCount(@1)); + + expect(table).to(haveCount(3)); + expect(table).notTo(haveCount(1)); + + NSString *msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(@1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(@3)); + }); + + + msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSSet { + NSSet *const set = [NSSet setWithArray:@[@1, @2, @3]]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSIndexSet { + NSIndexSet *const set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForUnsupportedTypes { + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(6)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m @@ -0,0 +1,33 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCMatchTest : XCTestCase + +@end + +@implementation ObjCMatchTest + +- (void)testPositiveMatches { + expect(@"11:14").to(match(@"\\d{2}:\\d{2}")); + expect(@"hello").toNot(match(@"\\d{2}:\\d{2}")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(@"hello").to(match(@"\\d{2}:\\d{2}")); + }); + expectFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got <11:22>", ^{ + expect(@"11:22").toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).to(match(@"\\d{2}:\\d{2}")); + }); + expectNilFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..9b5a378 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m @@ -0,0 +1,178 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCRaiseExceptionTest : XCTestCase + +@end + +@implementation ObjCRaiseExceptionTest + +- (void)testPositiveMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ @throw exception; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException().named(NSInvalidArgumentException)); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food")); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"})); + + expectAction(^{ }).toNot(raiseException()); +} + +- (void)testPositiveMatchesWithBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); +} + +- (void)testNegativeMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + + expectFailureMessage(@"expected to raise any exception, got no exception", ^{ + expectAction(^{ }).to(raiseException()); + }); + + expectFailureMessage(@"expected to raise exception with name , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(@"foo")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"cakes")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason with userInfo <{k = v;}>, got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"k": @"v"})); + }); + + expectFailureMessage(@"expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }", ^{ + expectAction(^{ [exception raise]; }).toNot(raiseException()); + }); +} + +- (void)testNegativeMatchesWithPassingBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectFailureMessage(@"expected to raise exception that satisfies block, got no exception", ^{ + expect(exception).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"LOL")); + })); + }); + + NSString *outerFailureMessage = @"expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).toNot(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(@"foo"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"bar"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); +} + +- (void)testNegativeMatchesWithNegativeBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + NSString *outerFailureMessage; + + NSString *const innerFailureMessage = @"expected to equal , got "; + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m new file mode 100644 index 0000000..5b38b83 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAllOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAllOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAllOf(equal(@2), beLessThan(@3))); + expect(@2).toNot(satisfyAllOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAllOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).toNot(satisfyAllOf(beTrue(), beFalse())); + expect(@YES).toNot(satisfyAllOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAllOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match all of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, and {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAllOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAllOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAllOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAnyOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAnyOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAnyOf(equal(@2), equal(@3))); + expect(@2).toNot(satisfyAnyOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAnyOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).to(satisfyAnyOf(beTrue(), beFalse())); + expect(@YES).to(satisfyAnyOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAnyOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match one of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, or {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAnyOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAnyOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAnyOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m @@ -0,0 +1,21 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSyncTest : XCTestCase + +@end + +@implementation ObjCSyncTest + +- (void)testFailureExpectation { + expectFailureMessage(@"fail() always fails", ^{ + fail(); + }); + + expectFailureMessage(@"This always fails", ^{ + failWithMessage(@"This always fails"); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m @@ -0,0 +1,52 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCUserDescriptionTest : XCTestCase + +@end + +@implementation ObjCUserDescriptionTest + +- (void)testToWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to equal <2>, got <1>", ^{ + expect(@1).toWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).toNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testNotToWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).notToWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToEventuallyWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to eventually equal <2>, got <1>", ^{ + expect(@1).toEventuallyWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToEventuallyNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toEventuallyNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToNotEventuallyWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toNotEventuallyWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m @@ -0,0 +1,31 @@ +@import XCTest; +@import Nimble; + +@interface ObjcStringersTest : XCTestCase + +@end + +@implementation ObjcStringersTest + +- (void)testItCanStringifyArrays { + NSArray *array = @[@1, @2, @3]; + NSString *result = NMBStringify(array); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItCanStringifyIndexSets { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + NSString *result = NMBStringify(indexSet); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItRoundsLongDecimals { + NSNumber *num = @291.123782163; + NSString *result = NMBStringify(num); + + expect(result).to(equal(@"291.1238")); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/script/release b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/script/release new file mode 100755 index 0000000..f61c0dc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/script/release @@ -0,0 +1,187 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Nimble +PODSPEC=Nimble.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=/tmp/nimble.release.notes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "---------------- Released as $VERSION_TAG ----------------" +echo + +echo +echo "Pushing to pod trunk..." + +# NOTE: remove allow-warnings after v9.0.0 of Nimble +$POD trunk push "$PODSPEC" --allow-warnings + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for GitHub styling." +echo " - Announce!" + +open "https://github.com/Quick/Nimble/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/test b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/test new file mode 100755 index 0000000..0766351 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Nimble/test @@ -0,0 +1,156 @@ +#!/bin/bash + +GREEN="\033[0;32m" +CLEAR="\033[0m" + +if which xcodebuild > /dev/null; then + echo -e "Gathering ${GREEN}xcodebuild sdk versions${CLEAR}..." + BUILD_DIR=`pwd`/build + LATEST_IOS_SDK_VERSION=`xcodebuild -showsdks | grep iphonesimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_TVOS_SDK_VERSION=`xcodebuild -showsdks | grep appletvsimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_MACOS_SDK_VERSION=`xcodebuild -showsdks | grep 'macosx' | cut -d ' ' -f 3 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + BUILD_IOS_SDK_VERSION=${NIMBLE_BUILD_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + RUNTIME_IOS_SDK_VERSION=${NIMBLE_RUNTIME_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + BUILD_TVOS_SDK_VERSION=${NIMBLE_BUILD_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + RUNTIME_TVOS_SDK_VERSION=${NIMBLE_RUNTIME_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + BUILD_MACOS_SDK_VERSION=${NIMBLE_BUILD_MACOS_SDK_VERSION:-$LATEST_MACOS_SDK_VERSION} +fi + +set -e + +function color_if_overridden { + local actual=$1 + local env_var=$2 + if [ -z "$env_var" ]; then + printf "$actual" + else + printf "$GREEN$actual$CLEAR" + fi +} + +function print_env { + echo "=== Environment ===" + echo " iOS:" + echo " Latest iOS SDK: $LATEST_IOS_SDK_VERSION" + echo " Building with iOS SDK: `color_if_overridden $BUILD_IOS_SDK_VERSION $NIMBLE_BUILD_IOS_SDK_VERSION`" + echo " Running with iOS SDK: `color_if_overridden $RUNTIME_IOS_SDK_VERSION $NIMBLE_RUNTIME_IOS_SDK_VERSION`" + echo + echo " tvOS:" + echo " Latest tvOS SDK: $LATEST_TVOS_SDK_VERSION" + echo " Building with tvOS SDK: `color_if_overridden $BUILD_TVOS_SDK_VERSION $NIMBLE_BUILD_TVOS_SDK_VERSION`" + echo " Running with tvOS SDK: `color_if_overridden $RUNTIME_TVOS_SDK_VERSION $NIMBLE_RUNTIME_TVOS_SDK_VERSION`" + echo + echo " macOS:" + echo " Latest macOS SDK: $LATEST_MACOS_SDK_VERSION" + echo " Building with macOS SDK: `color_if_overridden $BUILD_MACOS_SDK_VERSION $NIMBLE_BUILD_MACOS_SDK_VERSION`" + echo + echo "======= END =======" + echo +} + +function run { + echo -e "$GREEN==>$CLEAR $@" + "$@" +} + +function test_ios { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPad Air,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building + + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPhone 5s,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_tvos { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-tvOS" -configuration "Debug" -sdk "appletvsimulator$BUILD_TVOS_SDK_VERSION" -destination "name=Apple TV 1080p,OS=$RUNTIME_TVOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_macos { + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-macOS" -configuration "Debug" -sdk "macosx$BUILD_MACOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_podspec { + echo "Gathering CocoaPods installation information..." + run bundle exec pod --version + echo "Linting podspec..." + # Note: remove `--allow-warnings` once old Matcher API has been removed + run bundle exec pod lib lint Nimble.podspec --allow-warnings +} + +function test_swiftpm { + if [ -d .build ]; then + run swift build --clean + fi + run swift build && swift test +} + +function test_swiftpm_docker { + run docker build -t nimble-tests -f Dockerfile.test --no-cache . + run docker run -it --privileged=true nimble-tests +} + +function test() { + test_ios + test_tvos + test_macos + + if which swift-test; then + test_swiftpm + else + echo "Not testing with the Swift Package Manager because swift-test is not installed" + fi + + if which docker; then + test_swiftpm_docker + else + echo "Not testing linux in docker container since docker is not in PATH!" + fi +} + +function clean { + run rm -rf ~/Library/Developer/Xcode/DerivedData\; true +} + +function help { + echo "Usage: $0 COMMANDS" + echo + echo "COMMANDS:" + echo " all - Runs the all tests of macos, ios and tvos" + echo " clean - Cleans the derived data directory of Xcode. Assumes default location" + echo " help - Displays this help" + echo " ios - Runs the tests as an iOS device" + echo " macos - Runs the tests on macOS 10.10 (Yosemite and newer only)" + echo " podspec - Runs pod lib lint against the podspec to detect breaking changes" + echo " swiftpm - Runs the tests built by the Swift Package Manager" + echo " swiftpm_docker - Runs the tests built by the Swift Package Manager in a docker linux container" + echo " tvos - Runs the tests as an tvOS device" + echo + exit 1 +} + +function main { + print_env + for arg in $@ + do + case "$arg" in + clean) clean ;; + ios) test_ios ;; + tvos) test_tvos ;; + macos) test_macos ;; + podspec) test_podspec ;; + test) test ;; + all) test ;; + swiftpm) test_swiftpm ;; + swiftpm_docker) test_swiftpm_docker ;; + help) help ;; + esac + done + + if [ $# -eq 0 ]; then + clean + test + fi +} + +main $@ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..ebe5a2b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Quick/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitignore b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitignore new file mode 100644 index 0000000..6566a42 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitignore @@ -0,0 +1,66 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +.build/ +# Package.pins +# Package.resolved + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +# Mac OS X +.DS_Store + +# Quick +Quick.framework.zip diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitmodules b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitmodules new file mode 100644 index 0000000..cffbed0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Externals/Nimble"] + path = Externals/Nimble + url = https://github.com/Quick/Nimble.git diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.hound.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swift-version b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swift-version new file mode 100644 index 0000000..8c50098 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swift-version @@ -0,0 +1 @@ +3.1 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swiftlint.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swiftlint.yml new file mode 100644 index 0000000..79cda08 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.swiftlint.yml @@ -0,0 +1,8 @@ +disabled_rules: + - line_length + - type_name + - function_body_length + - identifier_name +included: + - Sources + - Tests diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.travis.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.travis.yml new file mode 100644 index 0000000..cdf7a69 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/.travis.yml @@ -0,0 +1,47 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + env: + - PLATFORM=macos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + osx_image: xcode9.3 + env: + - PLATFORM=macos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=ios + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=tvos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=swiftpm + - os: osx + osx_image: xcode9.3 + env: + - PLATFORM=swiftpm + - os: osx + env: + - PODSPEC=1 + - os: linux + sudo: required + dist: trusty + - os: linux + sudo: required + dist: trusty + env: + - SWIFT_VERSION=4.1 +install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./script/travis-install-macos; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./script/travis-install-linux; fi + - if [[ "$PODSPEC" ]]; then gem install bundler; bundle install; fi +script: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./script/travis-script-macos; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./script/travis-script-linux; fi + - if [[ "$PODSPEC" ]]; then danger; fi diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f82f39a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [quickorg@icloud.com](mailto:quickorg@icloud.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CONTRIBUTING.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CONTRIBUTING.md new file mode 100644 index 0000000..e8e32c1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/CONTRIBUTING.md @@ -0,0 +1,111 @@ + + +**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* + +- [Welcome to Quick!](#welcome-to-quick!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + - [Creating a Release](#creating-a-release) + + + +# Welcome to Quick! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Quick should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Quick / Nimble (eg - v0.7.0 or git sha `7d0b8c21357839a8c5228863b77faecf709254a9`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- After cloning the repository, run `git submodule update --init` to pull the Nimble submodule. +- Use `Quick.xcworkspace` to work on Quick. The workspace includes + Nimble, which is used in Quick's tests. + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of both Quick + and Nimble pass before submitting your pull request. You can run all + the iOS and OS X unit tests using `rake`. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. See `QuickSpec.m` for an example. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + Pull requests should be issued from personal forks. The Quick repo + should be reserved for long-running feature branches. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +Read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for more in depth guidelines. + +## Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Quick/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Announce! diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Dangerfile b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Dangerfile new file mode 100644 index 0000000..719de60 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Dangerfile @@ -0,0 +1,53 @@ +# set the number of lines that must be changed before this classifies as a 'Big PR' +@SDM_DANGER_BIG_PR_LINES = 50 + +# set the files to watch and fail if there are changes +@SDM_DANGER_IMMUTABLE_FILES = ['LICENSE', 'CONTRIBUTING.md', 'CODE_OF_CONDUCT.md'] + +# Sometimes it's a README fix, or something like that which is trivial +not_declared_trivial = !(github.pr_title.include? "#trivial") +has_app_changes = !git.modified_files.grep(/Sources/).empty? +no_test_modify = git.modified_files.grep(/Tests/).empty? + +# Warns when changing source files +if has_app_changes && not_declared_trivial && no_test_modify + warn("Need to add an unit test if you're modifying swift source") +end + +# determine if any of the files were modified +def did_modify(files_array) + did_modify_files = false + files_array.each do |file_name| + if git.modified_files.include?(file_name) || git.deleted_files.include?(file_name) + did_modify_files = true + end + end + return did_modify_files +end + +# Fail if changes to immutable files, such as License or CoC +fail('Do not modify the license or Code of Conduct') if did_modify(@SDM_DANGER_IMMUTABLE_FILES) + +# Make it more obvious that a PR is a work in progress and shouldn't be merged yet +warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" + +# Warn when there is a big PR +warn("Big PR") if git.lines_of_code > @SDM_DANGER_BIG_PR_LINES + +# Make a note about contributors not in the organization +unless github.api.organization_member?('Quick', github.pr_author) + # Pay extra attention if they modify the podspec + if git.modified_files.include?("*.podspec") + warn "External contributor has edited the Podspec file" + end +end + +# Mainly to encourage writing up some reasoning about the PR, rather than +# just leaving a title +if github.pr_body.length < 5 + warn "Please provide a summary in the Pull Request description" +end + +swiftlint.config_file = '.swiftlint.yml' +swiftlint.lint_files + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/README.md new file mode 100644 index 0000000..ea28bd1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/README.md @@ -0,0 +1,7 @@ +# Documentation + +- [English](en-us/README.md) +- [日本語](ja/README.md) +- [中文](zh-cn/README.md) +- [pt-br](pt-br/README.md) +- [한국어](ko-kr/README.md) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md new file mode 100644 index 0000000..fc7915b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md @@ -0,0 +1,220 @@ +# Effective Tests Using XCTest: Arrange, Act, and Assert + +Whether you're using XCTest, Quick, or another testing framework, you can write +effective unit tests by following a simple pattern: + +1. Arrange +2. Act +3. Assert + +## Using Arrange, Act, and Assert + +For example, let's look at a simple class called `Banana`: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +Let's verify the `Banana.peel()` method does what it's supposed to: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## Using Clear Test Names + +Our `testPeel()` makes sure that, if the `Banana.peel()` method ever +stops working right, we'll know. This usually happens when our application +code changes, which either means: + +1. We accidentally broke our application code, so we have to fix the application code +2. We changed how our application code works--maybe because we're adding a new + feature--so we have to change the test code + +If our tests start breaking, how do we know which one of these cases applies? It might +surprise you that **the name of the test** is our best indication. Good test names: + +1. Are clear about what is being tested. +2. Are clear about when the test should pass or fail. + +Is our `testPeel()` method clearly named? Let's make it clearer: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +The new name: + +1. Is clear about what is being tested: `testPeel` indicates it's the `Banana.peel()` method. +2. Is clear about when the test should pass: `makesTheBananaEdible` indicates the + banana is edible once the method has been called. + +## Testing Conditions + +Let's say we want to offer people bananas, using a function called `offer()`: + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +Our application code does one of two things: + +1. Either it offers a banana that's already been peeled... +2. ...or it offers an unpeeled banana. + +Let's write tests for these two cases: + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +Our test names clearly indicate the **conditions** under which our tests should pass: +in the case that `whenTheBananaIsPeeled`, `offer()` should `offersTheBanana`. And if +the banana isn't peeled? Well, we have a test for that, too! + +Notice that we have one test per `if` statement in our application code. +This is a great pattern when writing tests: it makes sure every set of conditions +is tested. If one of those conditions no longer works, or needs to be changed, we'll know +exactly which test needs to be looked at. + +## Shorter "Arrange" Steps with `XCTestCase.setUp()` + +Both of our `OfferTests` tests contain the same "Arrange" code: they both +create a banana. We should move that code into a single place. Why? + +1. As-is, if we change the `Banana` initializer, we'll have to change every test that creates a banana. +2. Our test methods will be shorter--which is a good thing if (and **only if**) that makes + the tests easier to read. + +Let's move the `Banana` initialization into the `XCTestCase.setUp()` method, which is called +once before every test method. + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## Sharing "Arrange" Code Across Multiple Tests + +If you find yourself using the same "arrange" steps across multiple tests, +you may want to define a helper function within your test target: + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> Use a function to define your helpers: functions can't be subclassed, nor + can they retain any state. Subclassing and mutable state can make your tests + harder to read. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md new file mode 100644 index 0000000..02ae0c0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md @@ -0,0 +1,87 @@ +# Don't Test Code, Instead Verify Behavior + +Tests should only fail if the application **behaves differently**. +They should test *what* the application code does, not *how* it does those things. + +- Tests that verify *what* an application does are **behavioral tests**. +- Tests that break if the application code changes, even if the behavior + remains the same, are **brittle tests**. + +Let's say we have a banana database, called `GorillaDB`. +`GorillaDB` is a key-value store for bananas. We can save bananas: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +And we can restore bananas from disk later: + +```swift +let banana = database.load(key: "my-banana") +``` + +## Brittle Tests + +How can we test this behavior? One way would be to check the size of the database +after we save a banana: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +Imagine, however, that the source code of `GorillaDB` changes. In order to make +reading bananas from the database faster, it maintains a cache of the most frequently +used bananas. `GorillaDB.size` grows as the size of the cache grows, and our test fails: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## Behavioral Tests + +The key to writing behavioral tests is determining exactly what you're expecting +your application code to do. + +In the context of our `testSave_savesTheBananaToTheDatabase` test: what is the +behavior we expect when we "save" a banana to the database? "Saving" implies, to me, +that we can load it later. So instead of testing that the size of the database increases, +we should test that we can load a banana. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +The key to writing behavioral tests is asking: + +- What exactly should this application code do? +- Is my test verifying *only* that behavior? + Or could it fail due to other aspects of how the code works? diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md new file mode 100644 index 0000000..7792963 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md @@ -0,0 +1,103 @@ +# Configuring How Quick Behaves + +You can customize how Quick behaves by subclassing `QuickConfiguration` and +overriding the `QuickConfiguration.Type.configure()` class method: + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +Projects may include several configurations. Quick does not make any +guarantee about the order in which those configurations are executed. + +## Adding Global `beforeEach` and `afterEach` Closures + +Using `QuickConfiguration.beforeEach` and `QuickConfiguration.afterEach`, you +can specify closures to be run before or after *every* example in a test suite: + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +In addition, Quick allows you to access metadata regarding the current +example being run: + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md new file mode 100644 index 0000000..3de82c5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md @@ -0,0 +1,28 @@ +# Installing Quick File Templates + +The Quick repository includes file templates for both Swift and +Objective-C specs. + +## Alcatraz + +Quick templates can be installed via [Alcatraz](https://github.com/supermarin/Alcatraz), +a package manager for Xcode. Just search for the templates from the +Package Manager window. + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Manually via the Rakefile + +To manually install the templates, just clone the repository and +run the `templates:install` rake task: + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +Uninstalling is easy, too: + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md new file mode 100644 index 0000000..258956f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md @@ -0,0 +1,157 @@ +# Installing Quick + +>Before starting, check [here](../../README.md#swift-version) which versions of Quick and Nimble are compatible with your version of Swift. + +Quick provides the syntax to define examples and example groups. Nimble +provides the `expect(...).to` assertion syntax. You may use either one, +or both, in your tests. + +There are three recommended ways of linking Quick to your tests: + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift Package Manager (experimental)](#swift-package-manager) + +Choose one and follow the instructions below. Once you've completed them, +you should be able to `import Quick` from within files in your test target. + +## Git Submodules + +To link Quick and Nimble using Git submodules: + +1. Add submodule for Quick. +2. If you don't already have a `.xcworkspace` for your project, create one. ([Here's how](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. Add `Quick.xcodeproj` to your project's `.xcworkspace`. +4. Add `Nimble.xcodeproj` to your project's `.xcworkspace`. It exists in `path/to/Quick/Externals/Nimble`. By adding Nimble from Quick's dependencies (as opposed to adding directly as a submodule), you'll ensure that you're using the correct version of Nimble for whatever version of Quick you're using. +5. Link `Quick.framework` and `Nimble.framework` in your test target's + "Link Binary with Libraries" build phase. + +First, if you don't already have one, create a directory for your Git submodules. +Let's assume you have a directory named `Vendor`. + +**Step One:** Download Quick and Nimble as Git submodules: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step Two:** Add the `Quick.xcodeproj` and `Nimble.xcodeproj` files downloaded above to +your project's `.xcworkspace`. For example, this is `Guanaco.xcworkspace`, the +workspace for a project that is tested using Quick and Nimble: + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step Three:** Link the `Quick.framework` during your test target's +`Link Binary with Libraries` build phase. You should see two +`Quick.frameworks`; one is for macOS, and the other is for iOS. + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +Do the same for the `Nimble.framework`, and you're done! + +**Updating the Submodules:** If you ever want to update the Quick +or Nimble submodules to latest version, enter the Quick directory +and pull from the master repository: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +Your Git repository will track changes to submodules. You'll want to +commit the fact that you've updated the Quick submodule: + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Cloning a Repository that Includes a Quick Submodule:** After other people +clone your repository, they'll have to pull down the submodules as well. +They can do so by running the `git submodule update` command: + +```sh +git submodule update --init --recursive +``` + +You can read more about Git submodules [here](http://git-scm.com/book/en/Git-Tools-Submodules). + +## CocoaPods + +First, update CocoaPods to Version 0.36.0 or newer, which is necessary to install CocoaPods using Swift. + +Then, add Quick and Nimble to your Podfile. Additionally, the ```use_frameworks!``` line is necessary for using Swift in CocoaPods: + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +Finally, download and link Quick and Nimble to your tests: + +```sh +pod install +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +As test targets do not have the "Embedded Binaries" section, the frameworks must +be added to the target's "Link Binary With Libraries" as well as a "Copy Files" build phase +to copy them to the target's Frameworks destination. + + > As Carthage builds dynamic frameworks, you will need a valid code signing identity set up. + +1. Add Quick to your [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate): + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. Run `carthage update`. +3. From your `Carthage/Build/[platform]/` directory, add both Quick and Nimble to your test target's "Link Binary With Libraries" build phase: + ![](http://i.imgur.com/pBkDDk5.png) + +4. For your test target, create a new build phase of type "Copy Files": + ![](http://i.imgur.com/jZATIjQ.png) + +5. Set the "Destination" to "Frameworks", then add both frameworks: + ![](http://i.imgur.com/rpnyWGH.png) + +This is not "the one and only way" to use Carthage to manage dependencies. +For further reference check out the [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md). + +## [Swift Package Manager](https://github.com/apple/swift-package-manager) +With the advent of the [swift.org](https://swift.org) open-source project, Swift now has an official, though nascent, package manager tool. Notably, this provides the possibility of using Quick on non-Apple platforms for the first time. Initial steps have been taken to allow using Quick to test projects using the Swift Package Manager, although frequent breakage is expected at this point since the tool is still under heavy development. + +Until further documentation has been written, the following repository may be useful as an example of how Quick can be declared as a dependency in a `Package.swift` file for SwiftPM: + +https://github.com/Quick/QuickOnLinuxExample + +### (Not Recommended) Running Quick Specs on a Physical iOS Device + +In order to run specs written in Quick on device, you need to add `Quick.framework` and +`Nimble.framework` as `Embedded Binaries` to the `Host Application` of the +test target. After adding a framework as an embedded binary, Xcode will +automatically link the host app against the framework. + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md new file mode 100644 index 0000000..65d7eba --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md @@ -0,0 +1,28 @@ +# More Resources + +## Examples of Quick Specs + +Quick is used by many companies, open-source projects, and individuals, +including [GitHub](https://github.com/github) and +[ReactiveCocoa](https://github.com/ReactiveCocoa). For examples, check out: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## More on Unit Testing for OS X and iOS Apps + +- **[Quality Coding](http://qualitycoding.org/)**: + A blog on iOS development that focuses on unit testing. +- **[OCMock Tutorials](http://ocmock.org/support/)**: + Use OCMock when you need "fake objects" in your tests. +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**: + Use this library to test code that sends requests to, and receives responses from, the Internet. +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + See [the Nimble documentation](https://github.com/Quick/Nimble) for instructions on how to write + custom matchers in Nimble. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md new file mode 100644 index 0000000..db68c40 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md @@ -0,0 +1,106 @@ +# Clearer Tests Using Nimble Assertions + +When code doesn't work the way it's supposed to, unit tests should make it +**clear** exactly what's wrong. + +Take the following function which, given a bunch of monkeys, only returns +the silly monkeys in the bunch: + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +Now let's say we have a unit test for this function: + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +The test fails with the following failure message: + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +The failure message leaves a lot to be desired. It leaves us wondering, +"OK, so something that should have been true was false--but what?" +That confusion slows us down, since we now have to spend time deciphering test code. + +## Better Failure Messages, Part 1: Manually Providing `XCTAssert` Failure Messages + +`XCTAssert` assertions allow us to specify a failure message of our own, which certainly helps: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +But we have to write our own failure message. + +## Better Failure Messages, Part 2: Nimble Failure Messages + +Nimble makes your test assertions, and their failure messages, easier to read: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +We don't have to write our own failure message--the one provided by Nimble +is already very readable: + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: verySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +The failure message makes it clear what's wrong: we were expecting `kiki` to be included +in the result of `silliest()`, but the result only contains `jane`. Now that we know +exactly what's wrong, it's easy to fix the issue: + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble provides many different kind of assertions, each with great failure +messages. And unlike `XCTAssert`, you don't have to type your own failure message +every time. + +For the full list of Nimble assertions, check out the [Nimble README](https://github.com/Quick/Nimble). +Below is just a sample, to whet your appetite: + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md new file mode 100644 index 0000000..dd8db21 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md @@ -0,0 +1,491 @@ +# Organized Tests with Quick Examples and Example Groups + +Quick uses a special syntax to define **examples** and **example groups**. + +In *[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)*, +we learned that a good test method name is crucial--when a test starts failing, it's +the best way to determine whether we have to fix the application code or update the test. + +Quick examples and example groups serve two purposes: + +1. They encourage you to write descriptive test names. +2. They greatly simplify the test code in the "arrange" step of your tests. + +## Examples Using `it` + +Examples, defined with the `it` function, use assertions to demonstrate +how code should behave. These are like test methods in XCTest. + +`it` takes two parameters: the name of the example, and a closure. +The examples below specify how the `Sea.Dolphin` class should behave. +A new dolphin should be smart and friendly: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +Use descriptions to make it clear what your examples are testing. +Descriptions can be of any length and use any character, including +characters from languages besides English, or even emoji! :v: :sunglasses: + +## Example Groups Using `describe` and `context` + +Example groups are logical groupings of examples. Example groups can share +setup and teardown code. + +### Describing Classes and Methods Using `describe` + +To specify the behavior of the `Dolphin` class's `click` method--in +other words, to test the method works--several `it` examples can be +grouped together using the `describe` function. Grouping similar +examples together makes the spec easier to read: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +When these two examples are run in Xcode, they'll display the +description from the `describe` and `it` functions: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +Again, it's clear what each of these examples is testing. + +### Sharing Setup/Teardown Code Using `beforeEach` and `afterEach` + +Example groups don't just make the examples clearer, they're also useful +for sharing setup and teardown code among examples in a group. + +In the example below, the `beforeEach` function is used to create a brand +new instance of a dolphin and its click before each example in the group. +This ensures that both are in a "fresh" state for every example: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +Sharing setup like this might not seem like a big deal with the +dolphin example, but for more complicated objects, it saves a lot +of typing! + +To execute code *after* each example, use `afterEach`. + +### Specifying Conditional Behavior Using `context` + +Dolphins use clicks for echolocation. When they approach something +particularly interesting to them, they release a series of clicks in +order to get a better idea of what it is. + +The tests need to show that the `click` method behaves differently in +different circumstances. Normally, the dolphin just clicks once. But when +the dolphin is close to something interesting, it clicks several times. + +This can be expressed using `context` functions: one `context` for the +normal case, and one `context` for when the dolphin is close to +something interesting: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +Strictly speaking, the `context` keyword is a synonym for `describe`, +but thoughtful use will make your spec easier to understand. + +### Test Readability: Quick and XCTest + +In [Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md), +we looked at how one test per condition was a great way to organize test code. +In XCTest, that leads to long test method names: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Using Quick, the conditions are much easier to read, and we can perform setup +for each example group: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## Temporarily Disabling Examples or Groups + +You can temporarily disable examples or example groups that don't pass yet. +The names of the examples will be printed out along with the test results, +but they won't be run. + +You can disable an example or group by prepending `x`: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## Temporarily Running a Subset of Focused Examples + +Sometimes it helps to focus on only one or a few examples. Running one +or two examples is faster than the entire suite, after all. You can +run only one or two by using the `fit` function. You can also focus a +group of examples using `fdescribe` or `fcontext`: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## Global Setup/Teardown Using `beforeSuite` and `afterSuite` + +Some test setup needs to be performed before *any* examples are +run. For these cases, use `beforeSuite` and `afterSuite`. + +In the example below, a database of all the creatures in the ocean is +created before any examples are run. That database is torn down once all +the examples have finished: + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +You can specify as many `beforeSuite` and `afterSuite` as you like. All +`beforeSuite` closures will be executed before any tests run, and all +`afterSuite` closures will be executed after all the tests are finished. +There is no guarantee as to what order these closures will be executed in. + +## Accessing Metadata for the Current Example + +There may be some cases in which you'd like the know the name of the example +that is currently being run, or how many have been run so far. Quick provides +access to this metadata in `beforeEach` and `afterEach` closures. + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md new file mode 100644 index 0000000..3fb6bdc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md @@ -0,0 +1,57 @@ +# Using Quick in Objective-C + +Quick works equally well in both Swift and Objective-C. + +There are two notes to keep in mind when using Quick in Objective-C, +however, which are described below. + +## The Optional Shorthand Syntax + +Importing Quick in an Objective-C file defines macros named `it` and +`itShouldBehaveLike`, as well as functions like `context()` and `describe()`. + +If the project you are testing also defines symbols with these names, you may +encounter confusing build failures. In that case, you can avoid namespace +collision by turning off Quick's optional "shorthand" syntax: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +You must define the `QUICK_DISABLE_SHORT_SYNTAX` macro *before* +importing the Quick header. + +Alternatively, you may define the macro in your test target's build configuration: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## Your Test Target Must Include At Least One Swift File + +The Swift stdlib will not be linked into your test target, and thus +Quick will fail to execute properly, if your test target does not contain +*at least one* Swift file. + +Without at least one Swift file, your tests will exit prematurely with +the following error: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +To fix the problem, add a blank file called `SwiftSpec.swift` to your test target: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> For more details on this issue, see https://github.com/Quick/Quick/issues/164. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/README.md new file mode 100644 index 0000000..d03f633 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/README.md @@ -0,0 +1,46 @@ +# Documentation + +Quick helps you verify how your Swift and Objective-C programs behave. +Doing so effectively isn't just a matter of knowing how to use Quick, +however. The guides in this directory can help you write +effective tests--not just using Quick, but even XCTest or other testing +frameworks. + +Each guide covers a particular topic. If you're completely new to unit +testing, consider reading them in the order they're introduced below: + +- **[Setting Up Tests in Your Xcode Project](SettingUpYourXcodeProject.md)**: + Read this if you're having trouble using your application code from within + your test files. +- **[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)**: + Read this to learn how to write `XCTestCase` tests that will help you write + code faster and more effectively. +- **[Don't Test Code, Instead Verify Behavior](BehavioralTesting.md)**: + Read this to learn what kinds of tests speed you up, and which ones will only end up + slowing you down. +- **[Clearer Tests Using Nimble Assertions](NimbleAssertions.md)**: + Read this to learn how to use Nimble to generate better failure messages. + Better failure messages help you move faster, by spending less time figuring out why + a test failed. +- **[Organized Tests with Quick Examples and Example Groups](QuickExamplesAndGroups.md)**: + Read this to learn how Quick can help you write even more effective tests, using + *examples* and *example groups*. +- **[Testing OS X and iOS Applications](TestingApps.md)**: + Read this to learn more about testing code that uses the AppKit and UIKit frameworks. +- **[Testing with test doubles](TestUsingTestDoubles.md)**: + Read this to learn what test doubles are and how to use them. +- **[Reducing Test Boilerplate with Shared Assertions](SharedExamples.md)**: + Read this to learn how to share sets of assertions among your tests. +- **[Configuring How Quick Behaves](ConfiguringQuick.md)**: + Read this to learn how you can change how Quick behaves when running your test suite. +- **[Using Quick in Objective-C](QuickInObjectiveC.md)**: + Read this if you experience trouble using Quick in Objective-C. +- **[Installing Quick](InstallingQuick.md)**: + Read this for instructions on how to add Quick to your project, using + Git submodules, CocoaPods, Carthage, or the Swift Package Manager. +- **[Installing Quick File Templates](InstallingFileTemplates.md)**: + Read this to learn how to install file templates that make writing Quick specs faster. +- **[More Resources](MoreResources.md)**: + A list of additional resources on OS X and iOS testing. +- **[Troubleshooting](Troubleshooting.md)**: + Read this when you experience other troubles. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..76e9d3e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md @@ -0,0 +1,89 @@ +# Setting Up Tests in Your Xcode Project + +With the exception of the Command Line Tool project type, when you create a new project in Xcode 7, a unit test target is included +by default. [See specific instructions for a Command Line Tool Project](#setting-up-a-test-target-for-a-command-line-tool-project). To write unit tests, you'll need to be able to use your main +target's code from within your test target. + +## Testing Swift Code Using Swift + +In order to test code written in Swift, you'll need to do two things: + +1. Set "Defines Module" in your `.xcodeproj` to `YES`. + + * To do this in Xcode: Choose your project, then "Build Settings", then "Packaging" header, + then "Defines Module" line, then select "Yes". Note: you may have + to choose "All" (Build Settings) instead of "Basic" to see the + "Packaging" section. + +2. `@testable import YourAppModuleName` in your unit tests. This will expose Any `public` and `internal` (the default) + symbols to your tests. `private` symbols are still unavailable. + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Quick integration in the Xcode Test Navigator suffers from some limitations (open [issue](https://github.com/Quick/Quick/issues/219)). Quick tests will not show up in the navigator until they've been run, repeat runs tend to reset the list in unpredictable ways and the tests cannot be run from the gutter next to the source code. +> Please file a radar to Apple and mention this as a duplicate to [rdar://26152293](http://openradar.appspot.com/radar?id=4974047628623872) to promote this feature request for Apple Engineers. + +> Some developers advocate adding Swift source files to your test target. +However, this leads to [subtle, hard-to-diagnose +errors](https://github.com/Quick/Quick/issues/91), and is not +recommended. + +## Testing Objective-C Code Using Swift + +1. Add a bridging header to your test target. +2. In the bridging header, import the file containing the code you'd like to test. + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +You can now use the code from `MyClass.h` in your Swift test files. + +## Testing Swift Code Using Objective-C + +1. Bridge Swift classes and functions you'd like to test to Objective-C by + using the `@objc` attribute. +2. Import your module's Swift headers in your unit tests. + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Testing Objective-C Code Using Objective-C + +Import the file defining the code you'd like to test from within your test target: + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### Setting Up a Test Target for a Command Line Tool Project + +1. Add a target to your project in the project pane. +2. Select "OS X Unit Testing Bundle". +3. Edit the scheme of your main target. +4. Select the "Test" node, click the "+" under the "Info" heading, and select + your testing bundle. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md new file mode 100644 index 0000000..339bf34 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md @@ -0,0 +1,125 @@ +# Reducing Test Boilerplate with Shared Assertions + +In some cases, the same set of specifications apply to multiple objects. + +For example, consider a protocol called `Edible`. When a dolphin +eats something `Edible`, the dolphin becomes happy. `Mackerel` and +`Cod` are both edible. Quick allows you to easily test that a dolphin is +happy to eat either one. + +The example below defines a set of "shared examples" for "something edible", +and specifies that both mackerel and cod behave like "something edible": + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Shared examples can include any number of `it`, `context`, and +`describe` blocks. They save a *lot* of typing when running +the same tests against several different kinds of objects. + +In some cases, you won't need any additional context. In Swift, you can +simply use `sharedExamples` closures that take no parameters. This +might be useful when testing some sort of global state: + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> In Objective-C, you'll have to pass a block that takes a + `QCKDSLSharedExampleContext`, even if you don't plan on using that + argument. Sorry, but that's the way the cookie crumbles! + :cookie: :bomb: + +You can also "focus" shared examples using the `fitBehavesLike` function. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md new file mode 100644 index 0000000..fc4f3f9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md @@ -0,0 +1,129 @@ +# Testing with Mocks + +## Test doubles + +Dependencies between objects can cause problems when writing tests. For example, say you have a `Car` class that depends on/uses `Tire`. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests` tests `Car`, which calls `Tire`. Now bugs in `Tire` could cause `CarTests` to fail (even though `Car` is okay). It can be hard to answer the question: "What's broken?". + +To avoid this problem, you can use a stand-in object for `Tire` in `CarTests`. In this case, we'll create a stand-in object for `Tire` called `PerfectTire`. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` will have all of the same public functions and properties as `Tire`. However, the implementation of some or all of those functions and properties will differ. + +Objects like `PerfectTire` are called "test doubles". Test doubles are used as "stand-in objects" for testing the functionality of related objects in isolation. There are several kinds of test doubles: + +- Mock object: Used for receiving output from a test class. +- Stub object: Used for providing input to a test class. +- Fake object: Behaves similarly to the original class, but in a simplified way. + +Let's start with how to use mock objects. + +## Mock + +A mock object focuses on fully specifying the correct interaction with other objects and detecting when something goes awry. The mock object should know (in advance) the methods that should be called on it during the test and what values the mock object should return. + +Mock objects are great because you can: + +- Run tests a lot quicker. +- Run tests even if you're not connected to the Internet. +- Focus on testing classes in isolation from their dependencies. + +### Writing Tests with Mock Objects in Swift + +#### Sample app + +For example, let's create an app which retrieves data from the Internet: + +* Data from the Internet will be displayed in `ViewController`. +* A custom class will implement the `DataProviderProtocol`, which specifies methods for fetching data. + +`DataProviderProtocol` is defined as follows: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` gets data from the Internet and returns it using a `callback` closure. + +Here is the `DataProvider` class, which conforms to the `DataProviderProtocol` protocol. + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = URL(string: "http://example.com/")! + let session = URLSession(configuration: .default) + let task = session.dataTask(with: url) { + (data, resp, err) in + let string = String(data: data!, encoding: .utf8) + callback(data: string) + } + task.resume() + } +} +``` + +In our scenario, `fetch()` is called in the `viewDidLoad()` method of `ViewController`. + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### Testing using a Mock of `DataProviderProtocol` + +`ViewController` depends on `DataProviderProtocol`. In order to test the view controller in isolation, you can create a mock object which conforms to `DataProviderProtocol`. + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +The `fetchCalled` property is set to `true` when `fetch()` is called, so that the test can confirm that it was called. + +The following test verifies that when `ViewController` is loaded, the view controller calls `dataProvider.fetch()`. + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvider = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvider = mockProvider + + expect(mockProvider.fetchCalled).to(beFalse()) + + let _ = viewController.view + + expect(mockProvider.fetchCalled).to(beTrue()) + } + } +} +``` + +If you're interested in learning more about writing tests, continue on to . diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md new file mode 100644 index 0000000..375cb5a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md @@ -0,0 +1,254 @@ +# Testing OS X and iOS Applications + +*[Setting Up Tests in Your Xcode Project](SettingUpYourXcodeProject.md)* +covers everything you need to know to test any Objective-C or Swift function or class. +In this section, we'll go over a few additional hints for testing +classes like `UIViewController` subclasses. + +> You can see a short lightning talk covering most of these topics + [here](https://vimeo.com/115671189#t=37m50s) (the talk begins at 37'50"). + +## Triggering `UIViewController` Lifecycle Events + +Normally, UIKit triggers lifecycle events for your view controller as it's +presented within the app. When testing a `UIViewController`, however, you'll +need to trigger these yourself. You can do so in one of three ways: + +1. Accessing `UIViewController.view`, which triggers things like `UIViewController.viewDidLoad()`. +2. Use `UIViewController.beginAppearanceTransition()` to trigger most lifecycle events. +3. Directly calling methods like `UIViewController.viewDidLoad()` or `UIViewController.viewWillAppear()`. + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## Initializing View Controllers Defined in Storyboards + +To initialize view controllers defined in a storyboard, you'll need to assign +a **Storyboard ID** to the view controller: + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +Once you've done so, you can instantiate the view controller from within your tests: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## Triggering UIControl Events Like Button Taps + +Buttons and other UIKit classes inherit from `UIControl`, which defines methods +that allow us to send control events, like button taps, programmatically. +To test behavior that occurs when a button is tapped, you can write: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` + +## Waiting for Asynchronous Operations with XCTestExpectation + +Tests sometimes need to wait for apps to complete operations such as animations and network calls that run asynchronously, either on a background queue or on a separate turn of the main run loop. (Aside: note that in most cases, tests should stub network calls and not actually use the network.) + +The standard XCTest way of handling asynchronous operations is to use [expectations](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html#//apple_ref/doc/uid/TP40014132-CH4-SW6). Quick supports these, but be careful! **Do not use `self` to get an instance of `XCTest`**. This includes creating or waiting for XCTest expectations: + +```swift +it("makes a network call") { + // 🛑 WRONG: don’t use self.expectation in Quick + let expectation = self.expectation(description: "network call") + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in expectation.fulfill() + }.resume() + // 🛑 WRONG: don’t use self.waitForExpectations in Quick + self.waitForExpectations(timeout: 1) +} +``` + +Why is this bad? Because when Quick runs your `spec()` function, it runs it on a dummy instance of `XCTest`. The real `XCTest` does not appear until those `it` closures actually run. In your `it` closures, `self` captures that dummy instance. Using this dummy instance to work with expectations is broken in two ways: + +- It sometimes fails with a “Questionable API usage” or “API violation” error. +- Sometimes it _appears_ to work, but even then it bypasses XCTest’s checks for common mistakes such as forgetting to call `waitForExpectations()`. + +The solution is to use `QuickSpec.current`, which returns the currently executing instance of XCTest: + +```swift +// Swift + +it("makes a network call") { + let expectation = QuickSpec.current.expectation(description: "network call") + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in expectation.fulfill() + }.resume() + QuickSpec.current.waitForExpectations(timeout: 1) +} +``` + +```objc +// Objective-C + +it(@"makes a network call", ^{ + XCTestExpectation *expectation = [QuickSpec.current expectationWithDescription:@"network call"]; + NSURLSessionTask *task = [NSURLSession.sharedSession + dataTaskWithURL: [NSURL URLWithString:@"https://example.com"] + completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { + [expectation fulfill]; + }]; + [task resume]; + [QuickSpec.current waitForExpectationsWithTimeout:1 handler:NULL]; +}); +``` + +### Nimble Alternative + +Nimble’s `expect(…).toEventually(…)` can also help test asynchronous operations: + +```swift +it("makes a network call") { + var networkCallCompleted = false + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in networkCallCompleted = true + }.resume() + expect(networkCallCompleted).toEventually(beTrue()) +} +``` + +This approach has several drawbacks: + +- It is not thread safe. You have to do your own synchronization if the condition you’re testing for isn’t fulfilled on the main thread. +- It provides no sanity checking for unwaited conditions. +- It can’t aggregate multiple expectations in a single wait. +- It is slower, because `fulfill` immediately triggers success whereas `toEventually()` polls for it. + +However, `toEventually()` can lead to simpler test code, and may be a better choice when these concerns do not apply. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md new file mode 100644 index 0000000..c39403c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md @@ -0,0 +1,9 @@ +# Common Installation Issues + +Here are solutions to common issues that come up when using the framework. + +## No such module 'Quick' + +- If you have already run `pod install`, close and reopen the Xcode workspace. If this does not fix the issue, continue below. +- Delete the _entire_ `~/Library/Developer/Xcode/DerivedData` direction, which includes `ModuleCache`. +- Explicitly build (`Cmd+B`) the `Quick`, `Nimble`, and `Pods-ProjectNameTests` targets after enabled their schemes from the Manage Schemes dialog. \ No newline at end of file diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md new file mode 100644 index 0000000..2f0a138 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md @@ -0,0 +1,212 @@ +# Effective Tests Using XCTest: Arrange, Act, and Assert + +XCTest や Quick に限らず、テストフレームワークを使用する際、このパターンに従うことで効率的なユニットテストを書くことができます。 + +1. Arrange(環境構築) +2. Act(実行) +3. Assert(動作確認) + +## パターンに従ってテストを書く + +例として Banana クラスを用意します。 + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +ここでは `Banana.peel()` のテストをしてみましょう。このメソッドの期待する振る舞いはこのようになります。 + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 簡潔なテスト名を用いる + +この `testPeel()` テストのおかげで `Banana.peel()` が正しく動作しない場合、すぐ気付くことができます。 +我々のアプリケーションコードを変更することで正しく動作しないケース(テストが失敗するケース)はしばしば起こります。 +テストが失敗する場合は下記どちらかのケースになります。 + +1. 間違えてアプリケーションコードを壊してしまっているため、直す必要がある +2. アプリケーションコードは期待したとおりに動いているが、もともと期待した機能が変わっているためテストコードを直す必要がある + +もしテストが失敗した場合、どちらのケースに当てはまる判断する必要が出てきます。そのためテスト名が分かりやすいことが重要になります。 + +良いテスト名とは、 + +1. 何をテストしているか明確であること +2. どのような時にテストがパスするか・失敗するか明確であること + +例に挙げた `testPeel()` は良いテスト名でしょうか?分かりやすくしてみましょう。 + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +新しいテスト名は、 + +1. 何をテストしているか明確である: `testPeel` は `Banana.peel()` メソッドをテストしてることを示す。 +2. どのような時にテストがパスするか明確である: `makesTheBananaEdible` はバナナが食べられるか(edible)どうかをテストしていることを示す。 + +## テスト時の条件 + +人々がバナナを欲しい時、`offer()` というメソッドを使います。 + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +私達のアプリケーションコードは2つのうちどちらかを実行します: + +1. 食べられる(すでに皮がむかれている)バナナを注文するか +2. まだ食べられない(すでに皮がむかれている)バナナを注文するか + +両方のケースをテストしてみましょう。 + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +私達のテスト名は'どのような条件でテストをパスするか'を明確に表しています。 +`whenTheBananaIsPeeled`, `offer()` のケースでは `offersTheBanana` となるべきです。またバナナの皮がむかれていない場合は? +ここでは両方共テストしています。 + +ここで大事なことはアプリケーションコード内の各`if`文に対してそれぞれ1つのテストを持っていることです。 +これはテストを書く際の重要なアプローチです。このアプローチでは全ての条件(if文)に関してテストされていることを保証します。 +テストのうちどれか1つがでも失敗するようになったらコードの見直しをする必要があります。テスト名が分かりやすいとすぐにチェックすべき箇所が分かります。 + +## `XCTestCase.setUp()`を用いて簡潔に環境構築をする + +`OfferTests` の2つのテストのどちらにも同じ"環境構築"のコードが入っています。 +どちらのテストでも banana を作っています。このコードは一箇所にまとめるべきです。なぜでしょう? + +1. そのままにしておく場合、もし `Banana` の生成方法が変わったら, 私たちは全てのテストを修正しないといけなくなります。 +2. テストコードが短くなり、テストの可読性が向上します。 + +Banana の生成方法を `XCTestCase.setUp()` の中に移しましょう。`XCTestCase.setUp()` は各テストの実行前に一度呼び出されます。 + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## 複数のテストにまたがって環境構築を共有する + +もし複数のテストにまたがって同じ環境構築のコードを使っている部分があれば、 test target 内に'ヘルパー関数'を定義しましょう。 + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 共通操作を定義するのに関数を使いましょう。関数は継承できず、状態を保持することができません。継承や状態を持たせる場合、テストの可読性が落ちてしまいます。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md new file mode 100644 index 0000000..af78e50 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md @@ -0,0 +1,81 @@ +# コードをテストせず、動作を確認する + +テストはアプリケーションが**期待と異なる動作** をした時のみ失敗するようにすべきです。 +アプリケーションコードが *何を* したかをテストすべきで、*どのように* したかをテストすべきではありません。 + +- アプリケーションが *何を* したかを確認するテストは **動作テスト(behavioral tests)** といいます。 +- アプリケーションの動作が変わっていなくても、コードを変更すると失敗するようになるテストは **脆弱なテスト(brittle tests)** といいます。 + +ここで `GorillaDB` というバナナのデータベースを用意します。 +`GorillaDB`は Key-Value 型のデータベースでバナナを保存することができます。 + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +そしてバナナをディスクから取り出すことができます。 + +```swift +let banana = database.load(key: "my-banana") +``` + +## 脆弱なテスト(Brittle Tests) + +どのようにして動作をテストするのでしょう?一つの方法としてここではバナナを保存した後にバナナのデータベースのサイズをチェックします。 + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + +ここで `GorillaDB` のソースコードを変更したとします。データベースからの読み出しを速くするためにもっとも頻繁に使用するバナナをキャッシュに保持するようにします。 +`GorillaDB.size` はキャッシュのサイズに合わせて大きくなります。この場合ディスクに保存しなくなるため上記のテストは失敗します。 + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 動作テスト(Behavioral Tests) + +動作のテストの重要なポイントは アプリケーションコードに期待する動作を明確にすることです。 + +`testSave_savesTheBananaToTheDatabase` というテストで期待する動作は バナナをデータベースに "保存する" ことでしょうか? +"保存する"というのは 後から読み出すことができる、という意味です。そのためデータベースのサイズが大きくなることをテストするのではなく、 +バナナを読み出すことができるかをテストすべきです。 + + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +動作テストを書く際の重要なポイント: + +- アプリケーションコードが何をすべきか明確にしているか? +- テストが *動作のみ* をテストしているか?コードの動作が他の要因で意図しない動きにならないか。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md new file mode 100644 index 0000000..3c2432f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md @@ -0,0 +1,101 @@ +# Quickの挙動をカスタマイズしましょう + +`QuickConfiguration` を継承したクラスを作成し、`QuickConfiguration.Type.configure()` をオーバーライドすることで Quick の挙動をカスタマイズすることができます。 + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +一つのプロジェクトで複数の configuration を持つこともできますが +どの順に configuration が実行されるか保証されません。 + +## テスト全体で使う `beforeEach` と `afterEach` を追加する + +`QuickConfiguration.beforeEach` と `QuickConfiguration.afterEach` を使うと +テストスイート内の各テストの実行前・実行後に走らせる処理を記述することができます。 + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +さらに現在実行中のテストに関するメタデータを取得することもできます。 + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md new file mode 100644 index 0000000..1c87e52 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md @@ -0,0 +1,26 @@ +# Quickファイル・テンプレートのインストール方法 + +Quick のリポジトリには Swift, Objective-C の両方で使用できるテンプレートが含まれています。 + +## Alcatraz + +Quick のテンプレートは Xcode のパッケージマネージャーの [Alcatraz](https://github.com/supermarin/Alcatraz) 経由でインストールできます。 +パッケージマネージャーから検索してみてください。 + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Rakefile から手動でインストールする + +手動でインストールすることもできます。 +リポジトリを clone して rake task の `templates:install` を実行してください。 + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +アンインストールも簡単です、下記コマンドを実行してください。 + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md new file mode 100644 index 0000000..884b8a5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md @@ -0,0 +1,152 @@ +# Quickのインストール方法 + +> **もし Xcode 7.1 を使用していたら** 現時点で最新バージョンの Quick--`v0.9.0` を使用してください +> 最新のリリースは `swift-2.0` branch で開発されています。 + +Quick は examples(テスト) and example groups(テストグループ)の文法を提供します。 +Nimble は `expect(...).to` の文法を提供します。 +テストでは両方を使ってもいいですし、どちらか片方を使う、ということもできます。 + +Quick をテストに組み込むには3つの方法があります。 + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) + +下記のインストール手順の中からどれか選択してインストールを進めてください。 +インストール完了後、テストターゲット内のファイルで Quick を使用(`import Quick`)できるようになります。 + +## Git Submodules + +Git submodules を使って Quick と Nimble をリンクします。手順の流れとしては下記の通りです。 + +1. Quick を submodule として追加. +2. プロジェクトで`.xcworkspace`を使っていなければ作成してください。 ([こちらを参照](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. `Quick.xcodeproj` をプロジェクトの`.xcworkspace`に追加してください。 +4. `Nimble.xcodeproj` をプロジェクトの`.xcworkspace`に追加してください。 `Nimble.xcodeproj` は `path/to/Quick/Externals/Nimble` にあります。 Quick が依存している Niimble を追加することで Quick のバージョンと Nimble のバージョンを合わせられます。 + +5. `Quick.framework` と `Nimble.framework` を BuildPhase の "Link Binary with Libraries" でリンクします。 + +もしまだ git submodules 用のディレクトリを作っていなかったら、まず始めにディレクトリを作成します。 +`Vendor` という名前のディレクトリを用意しましょう。 + +**Step 1:** Quick と Nimble を Git submodules としてダウンロードする + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step 2:** `Quick.xcodeproj` と `Nimble.xcodeproj` をプロジェクトの `.xcworkspace` に追加してください。 +例として `Guanaco.xcworkspace` という workspace に Quick と Nimble を追加します。 + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step 3:** build phase の `Link Binary with Libraries` に `Quick.framework` を追加してください。 +2種類の `Quick.frameworks` が表示されますが 1 つは OS X 用で、もう 1 つが iOS 用です。 + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +`Nimble.framework` も同様に追加してください。これで完了です! + +**Submodules をアップデートする:** Quick と Nimble を最新バージョンにアップデートしたい場合は Quick ディレクトリに入って master リポジトリから pull してください。 + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +あなたのプロジェクトの Git リポジトリは submodule の変更もトラッキングしているので Quick submodules の更新を commit しておきます。 + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Quick Submodule を含んだ リポジトリを git clone する:** 他の開発者があなたのリポジトリを clone したあと、submodules を同様に pull してくる必要があります。`git submodule update` コマンドを実行することで pull できます。 + +```sh +git submodule update --init --recursive +``` + +git submodules に詳細な情報は[こちら](http://git-scm.com/book/en/Git-Tools-Submodules)です。 + +## CocoaPods + +CocoaPods でインストールする場合、バージョンは 0.36.0 以降である必要(CocoaPods が Swift をサポートしているバージョン)があります。 + +Podfile に Quick と Nimble を追加して下さい。 Swift では ```use_frameworks!``` も必要です。 + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick', '~> 0.9.0' + pod 'Nimble', '3.0.0' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +その後 pod install でダウンロード、リンクします。 + +```sh +pod install +``` + +### Swift 1.2 で使う + +Quick の最新版(0.4.0)は Swift 2 (Xcode 7) 用ですが、Nimble の最新版(1.0.0) は Swift 1.2 (Xcode 6) 用です。 + +もし Xcode6 で使いたい場合は下記のようにバージョン指定してください。 + +```sh +target 'MyTests' do + use_frameworks! + pod 'Quick', '~>0.3.0' + pod 'Nimble', '~>1.0.0' +end +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +テストターゲットは "Embedded Binaries" section がないので framework はターゲットの "Link Binary With Libraries" に追加する必要があります。 build phase の "Copy Files" も同様にターゲットの framework destination を指定して下さい。 + + > Carthage は dynamic frameworks をビルドするので code signing identity に有効なものを設定しておく必要があります。 + +1. Quick を [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) に追加してください。 + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. `carthage update` を実行してください。 +3. `Carthage/Build/[platform]/` ディレクトリから Quick と Nimble をテストターゲットの "Link Binary With Libraries" に追加してください。 + ![](http://i.imgur.com/pBkDDk5.png) + +4. テストターゲットの build phase で "New Copy Files Phase" を選択してください。 + ![](http://i.imgur.com/jZATIjQ.png) + +5. "Destination" を "Frameworks" に設定して、2つの framework を追加してください。 + ![](http://i.imgur.com/rpnyWGH.png) + +Carthage の dependency の管理方法はこの方法だけではありません。 +詳細な情報はこちらを参照してください [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md) 。 + +### (非推奨) 実機で Quick のテストを走らせる + +Quick で書かれたテストを実機で走らせるためには `Quick.framework` と `Nimble.framework` を `Embedded Binaries` としてテストターゲットの `ホストアプリケーション` に追加されます。 Embedded binary として framework を追加すると Xcode が自動的にホストアプリケーションにリンクしてしまいます。 + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md new file mode 100644 index 0000000..996f2df --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md @@ -0,0 +1,27 @@ +# その他の参考資料 + +## Quick のテストのサンプル + +Quick は[GitHub](https://github.com/github)や[ReactiveCocoa](https://github.com/ReactiveCocoa)を含む多くの企業、OSS プロジェクト、個人で利用されています。 + +下記リポジトリを参考にしてみてください。 + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/Moya/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## OS X と iOS Apps のテストに関する参考資料 + +- **[Quality Coding](http://qualitycoding.org/)**: + ユニットテストにフォーカスした iOS 開発に関するブログ。 +- **[OCMock Tutorials](http://ocmock.org/support/)**: + テストでモックが必要な時に使用する OCMock のチュートリアル。 +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**: + 通信を行うコードをテストする時はこのライブラリを使用して下さい。 +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + Nimble の matcher の書き方に関するドキュメントはこちら([the Nimble documentation](https://github.com/Quick/Nimble)) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md new file mode 100644 index 0000000..429d6a4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md @@ -0,0 +1,100 @@ +# Nimble Assertions を使ってテストをより簡潔に + +テストが期待した通りに動作しない時、ユニットテストは **何が問題か** を明確にすべきです。 + +次の関数はサルの集団から馬鹿なサルだけを取得します。 + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +ここでこの関数に対するテストを書いてみましょう。 + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +このテストは下記のメッセージとともに失敗します。 + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +失敗した時は多くの情報を残すことが望ましいです。このメッセージのままではよく分かりません。 +true や false だけではそれがなにか分かりません。このままではテストコードから原因を見つけるまでに時間がかかってしまいます。 + +## 良い失敗メッセージを残す: Part 1: XCTAssert に手動でメッセージを渡す + +`XCTAssert` は失敗時にメッセージを指定することができます。 + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +しかし`XCTAssert`では自分でメッセージを指定しないといけません。 + +## 良い失敗メッセージを残す: Part 2: Nimble Failure Messages を使う + +Nimble は Assert, 失敗時のメッセージを読みやすくしてくれます。 + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +Nimble では自分でメッセージを指定しなくても Nimble がとても読みやすいメッセージを返してくれます。 + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: verySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +失敗メッセージは何が問題かを明確にします:ここでは `kiki` が `silliest()` の戻り値に含まれることを期待していますが +このテストでは `jane` しか含まれていません。Nimble からのメッセージで何が問題かが分かりやすく伝えられるので、簡単に直すことができます。 + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble は具体的な失敗メッセージを返してくれる多くの種類の Assertion を提供します。 +`XCTAssert` と違って毎回自分でメッセージを指定することはありません。 + +Nimble の全ての assertion はこちらで確認できます: [Nimble README](https://github.com/Quick/Nimble) 。 +下記に幾つかの例を示します。 + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md new file mode 100644 index 0000000..9b1d161 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md @@ -0,0 +1,477 @@ +# QuickのExamplesとExample Groupsで、たくさんのテストでも整理整頓 + +Quick では **examples** と **example groups** という特別な文法があります。 + +*[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)* では, +良いテスト名をつけることがとても重要だということを学びました。 +テストが失敗した時、テスト名はアプリケーションコードを直すべきかテストを修正すべきかを判断する際の重要な材料になります。 + +Quick の examples(テスト) と example groups(テストグループ) は二つの役に立ちます。 + +1. 記述的なテスト名を書くためことをサポートします +2. テスト中の "環境構築" 部分におけるコードを簡略化します + +## Examples の `it` + +Examples は `it` という「コードがどのように動作すべきかを宣言する」関数を持ちます。 +これは XCTest の test methods のようなものです。 + +`it` 関数は2つのパラメータ、example の名前と closure です。 +下記のテストでは `Sea.Dolphin` クラスがどのように動作すべきかを記述しています。 +この example では「新しく生成された Dolphin は smart で friendly であるべき」と書いています。 + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +Examples が何をテストしているかを明確にするために Description を使います。 +Description は文字数制限がなくどの文字でも(絵文字さえも!)使うことができます。 +:v: :sunglasses: + +## Example Groups の `describe` と `context` + +Example groups では Example のグルーピングができ、 setup と teardown のコードを共有できます。 + +### `describe` を使ってクラスと関数について記述する + +`Dolphin` クラスの `click` 関数の動作を記述する際に、 +言い換えると関数が動作していることをテストする際に、 +複数の `it` example を `describe` を用いてグルーピングすることができます。 +似ている examples をまとめることで可読性が向上します。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +Xcode でこれらの examples を実行すると`describe` と `it` の記述内容も表示されます。上記のテストの場合、下記のような出力になります。 + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +それぞれの Example が何をテストしているかが明確ですね。 + +### `beforeEach` と `afterEach` を使って Setup/Teardown のコードを共有する + +Example groups はテストの内容をただ分かりやすくするだけでなく同一グループ内のsetup/teardownコードを共有することができます。 + +下記の例では`its click`の Example group のテストを実行する前に `beforeEach`を使って新しい Dolphin のインスタンスを生成しています。 +各 Example において "新しい" 状態でテストが行えます。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +この例では setup を共有することはあまりメリットがないように見えるかもしれませんが +複数の複雑なオブジェクトを生成する時などコード量を節約することができます。 + +それぞれの Example を実行した後に実行したいコードについては`afterEach`を使います。 + +### `context` を使ってある条件での動作を記述する + +例の Dolphins(イルカ達) はエコーロケーションのために カチッと音を立てます(`click` 関数を呼び出します)。 +イルカ達は特に興味のあるものに近づく時、それが何かを調べるために連続してエコーロケーション(`click` 関数を呼び出します)を行います。 + +このシナリオにおいてテストが 異なる状況において `click` 関数の動作は異なる ということを表す必要があります。 + +基本的にイルカは一度音を鳴らすだけですが、イルカ達が興味があるものが近くにあると連続して音を鳴らします。 + +この状況について `context` 関数を使って表します。ある `context` では通常のケースで、もう一方の`context`ではイルカが興味あるものに近づいているケースです。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +厳密には `context` キーワードは `describe`と同じですがテストを理解しやすくなるので使い分けるとよいです。 + +### テストの可読性: Quick と XCTest + +*[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)*で各条件についてそれぞれテストを用意するのがテストを書く際の重要な方法と述べましたが +このアプローチで XCTest でテストを書くとテスト名が長くなってしまいます。 + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Quick を使うと条件について読みやすく、しかもそれぞれの Example group について環境構築が効率的に行えます。 + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 一時的に Examples や Example Groups を無効にする + +通っていない Example を一時的に無効にすることもできます。 +Example や Example Groups の先頭に `x` をつけると無効になります。 +Examples の名前がテスト結果の中に出力されますがテストは実行されなくなります。 + + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 指定した Examples だけ一時的に実行する + +一部の Example だけ実行できると便利なこともあります。 +そのような時は実行したい Example を `fit` 関数を用いて指定します。 +特定の Example group だけ実行したい時は`fdescribe` か `fcontext` を記述します。 +※もともと書いてあるテストコードの先頭に `f` を追記するだけです。 + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## `beforeSuite` と `afterSuite` を使ってテスト全体に対する Setup/Teardown を行う + +テストの環境構築の中にはどの Example よりも先に、または最後に実行したいものがある場合もあります。 +このような時は `beforeSuite` か `afterSuite` を使います。 + +下記の例では 全ての Example が実行される前に一度だけ海の全ての生物のデータベースが生成され、全ての Exmample が実行された後にデータベースを削除しています。 + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +`beforeSuite` and `afterSuite` は必要な数だけ定義することができます。 +全ての `beforeSuite` の closure は全てのテストが実行される前に実行され、 +全ての `afterSuite` の closure は全てのテストが実行された後に実行されます。 + +複数の `beforeSuite`(`afterSuite`) の closure を記述した場合、これらの実行順序は記述した順序で実行されるかは保証されません。 + +## 実行中の Example でメタデータにアクセスする + +実行中の Example の中で、Example名を知りたいケース、これまでに何件の Example を実行したかを知りたいケースがあるかもしれません。 +Quick ではこれらの情報に `beforeEach` と `afterEach` の closure の中からアクセスすることができます。 + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md new file mode 100644 index 0000000..6d67044 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md @@ -0,0 +1,48 @@ +# Objective-C で Quick を使う + +Quick は Swift でも Objective-C でも問題なく動作します。 + +ですが、Objective-C で Quick を使う場合、2点気を付けておきべきことがあります。 + +## 簡略記法 + +Objective-C で Quick を import すると `it` と `itShouldBehaveLike` というマクロが定義されます。 +また、`context()` and `describe()`といった関数も同様に定義されます。 + +もしプロジェクトですでに同じ名前のシンボルを定義していた場合、重複のためビルドエラーになります。 +その場合は下記のように`QUICK_DISABLE_SHORT_SYNTAX`を定義してこの機能を無効にしてください。 + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +`QUICK_DISABLE_SHORT_SYNTAX`マクロは Quick ヘッダを import する前に定義する必要があります。 + + +## Swift のファイルを テストターゲットに含める + +テストターゲットの中に Swift のファイルが含まれていないと Swift stlib が リンクされないため Quick が正しく実行されません。 + +Swift のファイルが含まれていないと下記のようなエラーが発生します。 + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +修正するためには `SwiftSpec.swift` という名前の空のファイルをテストターゲットに追加してください。 + +```swift +// SwiftSpec.swift + +import Quick +``` + +> この問題に関する詳細情報はこちら https://github.com/Quick/Quick/issues/164. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/README.md new file mode 100644 index 0000000..0c4f0d5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/README.md @@ -0,0 +1,50 @@ +# テストの書き方、Quickの使い方 + +Quickでテストを書くと、SwiftとObjective-Cで書かれたプログラムがどう動作しているか楽に確認できます。 + +ところが、有用なテストはQuickを使わなくても書けます。 +役に立つテストが書けるようになるには、Quickのようなフレームワークの使い方を覚える必要はありません。 + +このディレクトリにあるファイルは、QuickかXCTestかを問わず、 +「役に立つ」テストとは何か、そしてどうやってそういったテストが書けるか、 +それを拙文ながら説明しようとしています。 + +目次: + +(テストについて事前知識がまったくない方は、順に読んでいくことをオススメします。) + +- **[Xcodeでテストを用意しましょう](SettingUpYourXcodeProject.md)**: + アプリのコードがテスト・ファイルから参照できない場合や、 + その他スムーズにテストが動かない場合はこのファイルを読み返すといいかもしれません。 +- **[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)**: + 役に立つテストを書くための基本中の基本。これさえ覚えれば、 + XCTestを使ってあなたも正確に動作するコードをすばやく書けるようになります。 +- **[コードをテストするのではなく、動作の確認をしましょう](BehavioralTesting.md)**: + 同じ「テスト」でも、開発を進めやすくするテストと、邪魔ばかりするテストとがあります。 + 見分ける方法は、このファイルを読めば分かります。 +- **[Nimbleのassertでテストをより読みやすくしましょう](NimbleAssertions.md)**: + Nimbleを使って、テストが失敗したときわかりやすいエラーメッセージを出すようにしましょう。 + わかりやすいメッセージで、テストがなぜ失敗したのかが一瞬でわかって開発の速度があがります。 +- **[QuickのExamplesとExample Groupsで、たくさんのテストでも整理整頓](QuickExamplesAndGroups.md)**: + Quickを使う大きなメリットのひとつはexamplesとexample groupsです。 + これでより簡潔にたくさんのテストが書けるようになります。 +- **[OS XとiOSアプリのテスト](TestingApps.md)**: + AppKitとUIKitを使ったコードをどうやってテストできるか説明します。 +- **[Test doublesを使ったテスト](TestUsingTestDoubles.md)**: + Test doublesを使って対象のクラスのみをテストする方法を説明します。 +- **[assertの共有でボイラープレートコードをなくしましょう](SharedExamples.md)**: + どうやってassertを共有できるか、なぜそうするのが望ましいのか説明します。 +- **[Quickの挙動をカスタマイズしましょう](ConfiguringQuick.md)**: + Quickがテストを実行するときの挙動をどうやって変えられるか説明します。 +- **[Objective-CでQuickを使う方法・注意点](QuickInObjectiveC.md)**: + QuickをObjective-Cで使ったときに思わぬ不具合・トラブルがあった場合、 + これを読んでください。 +- **[Quickのインストール方法](InstallingQuick.md)**: + あなたのプロジェクトにQuickを導入する方法を説明します。Git submodules、 + CocoaPods、Carthage、全部サポートしています! +- **[Quickファイル・テンプレートのインストール方法](InstallingFileTemplates.md)**: + Quickテストをすばやく作成するためのファイル・テンプレートをインストールする方法を説明します。 +- **[その他の参考資料](MoreResources.md)**: + OS X・iOSのテストに関しての資料集を用意しています。 +- **[トラブルシューティング](Troubleshooting.md)**: + その他の不具合に遭遇した場合にこれを読んでください。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..9258217 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md @@ -0,0 +1,77 @@ +# テストの準備をする + +Xcode7 では Command Line Tool プロジェクトを除き、デフォルトで Unit test target が生成されます。 [参照:コマンドラインツールプロジェクトでテストの準備をする](#コマンドラインツールプロジェクトでテストの準備をする)。 +テストを書くためには Unit test targetから Main target のコードが使用できる必要があります。 + +## Swift のコードを Swift でテストする + +Swift で書かれたコードをテストするためには下記2つの作業を行います。 + +1. プロジェクトファイル `.xcodeproj` の "defines module" を `YES` に設定します。 + + * Xcode で対象のプロジェクトを開き、"Build Settings" の "Defines Modules" の 項目を "Yes" にします。 + +2. 各テストファイルで `@testable import YourAppModuleName` を追記します。 追記することで public, internal のシンボルにアクセスできるようになります。`private` シンボルはアクセスできないままです。 + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Swift のファイルを Test target に含める、という方法もありますが、不具合を引き起こす([subtle, hard-to-diagnose +errors](https://github.com/Quick/Quick/issues/91)) ことがあるためお勧めしません。 + +## Objective-C のコードを Swift でテストする + +1. Bridging header を test target に追加します。 +2. Bridging header 内で テストしたいコードを import します。 + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +これで `MyClass.h` のコードを Swift のテストコードから使用できるようになります。 + +## Swift のコードを Objective-C でテストする + +1. テストしたい Swift のクラスと関数に`@objc`属性を付加します。 +2. テストコードで Module の Swift header を import します。 + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Objective-C のコードを Objective-C でテストする + +テストコード内でテスト対象を import します。 + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### コマンドラインツールプロジェクトでテストの準備をする + +1. プロジェクトのペインからターゲットを追加(+ボタンを押下) +2. "OS X Unit Testing Bundle" または "iOS Unit Testing Bundle" を選択 +3. Main target で "Edit the scheme" を選択 +4. "Test" を選択, "Info" タブで "+" をクリックして追加した testing bundle を選択 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md new file mode 100644 index 0000000..a1670d2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md @@ -0,0 +1,122 @@ +# assertの共有でボイラープレートコードをなくしましょう + +複数のオブジェクトに対象して同じ内容のテストを行いたい場合があります。 + +例えば `Edible` という protocol があるとします。 +イルカ(dolphin)が何か食べられる(`Edible`な)ものを食べるとイルカが幸せになります。 +サバ(`Mackerel`)とタラ(`Cod`)は食べられる(`Edible`な)ものです。 + +Quick は「イルカがどちらかを食べて幸せになる」ということを簡単にテストすることできます。 + +下記で示すテストは "(何かを食べる)something edible" という共有できるテスト(Shared examples)を定義しています。 +また、この共有できるテストでサバ(Mackerel)とタラ(Cod)を食べることについてのテストを記述しています。 + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Shared examples は `it`, `context` や `describe` のブロックをいくつでも含めることができます。 +これは異なる種類の対象についてテストをする際のコードを節約することができます。 + +あるケースでは context を追加する必要もありません。 +Swift では `sharedExamples` closure を使って共有できるテストを定義することができます。 +このテクニックはある時点での状態をテストしたい時などに役に立つかもしれません。 + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Objective-Cでは, `QCKDSLSharedExampleContext` を引数に取る block を渡すことができます。※QCKDSLSharedExampleContext を使う予定がなくても引数に取る block を用意してください。めんどくさくても。世の中そんなもんです。 :cookie: :bomb: + +`itBehavesLike` の先頭に `f` を加えて(`fitBehavesLike`) として共有できるテストのみ実行することもできます。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md new file mode 100644 index 0000000..7251e2e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md @@ -0,0 +1,138 @@ +# Test doubles を使ったテスト + +## Test doubles + +テストを書いているとしばしば次のような問題にぶつかります。 `車`クラスが`タイヤ`クラスを使用している(依存している)とします。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +ここで 車Tests という (`タイヤ`に依存している)`車` のテストを用意します。ここで `タイヤ` にバグがあった場合、`車`に問題なくても 車Tests は失敗します。 +このような事が頻繁に起こるとバグの究明が難しくなります。 + +この問題を回避するには、`車`Tests において `タイヤ`の 代わりになるクラス`完璧タイヤ` クラス(代理、英語で `Stand-in`といいます)を用意する、という方法があります。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +この`完璧タイヤ`は実装は異なりますが`タイヤ`と同じメソッド、プロパティを持ちます。そのため 車Tests において `タイヤ` を `完璧タイヤ` と入れ替えることができます。 + +`完璧タイヤ`クラスのような差し替え可能なオブジェクトのことを一般に'test doubles(テストダブル)'と呼びます。 +'test doubles' にはいくつか種類があります。 + +- Mock object: テスト対象のクラスの出力の検証に用いる +- Stub object: テスト対象のクラスにデータを渡す(入力)際に用いる +- Fake object: 差し替え前のオブジェクトと近い振る舞いをする(実装がより簡単になっている) + +ここではモックを使ったテストの方法を紹介します。 + +## モックとは + +モックとはテスト対象のオブジェクト(クラス、構造体)が呼び出し先のオブジェクトと意図したとおりに協調動作するかどうかをテストするために使うオブジェクトのことです。 + +## Swift でモックを使ったテストを書く + +### サンプルアプリケーション + +ここでは例としてインターネット経由で取得したデータを表示するアプリケーションを考えます。 + +* DataProviderProtocolというプロトコルを実装したクラスがインターネット経由でデータを取得する +* 取得したデータをViewControllerで表示する + +ここで DataProviderProtocol を定義します。 + +```swift +// Swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +DataProviderProtocol の `fetch()`関数でデータを取得し、callbackブロックでデータを渡します。 + +ここで DataProviderProtocol を実装する DataProvider クラスを定義します。 + +```swift +// Swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = NSURL(string: "http://example.com/")! + let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) + let task = session.dataTaskWithURL(url, completionHandler: { + (data, resp, err) in + let string = NSString(data:data!, encoding:NSUTF8StringEncoding) as! String + callback(data: string) + }) + task.resume() + } +} +``` + +ViewController の `viewDidLoad` 中にデータの取得(`fetch()`の呼び出し)を行います。 + +コードはこのようになります。 + +```swift +// Swift +class ViewController: UIViewController { + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +## DataProviderProtocol のモックを使ったテストを書く + +この例では ViewController は DataProviderProtocol に依存しています。 +テスト用に DataProviderProtocol を継承したクラス(モックとして使用します)をテストターゲット内に作成します。 + +モックを作成することで、 +- テストを速く実行できる +- インターネットに接続していなくてもテストができるようになる +- ViewController の動作のテストにフォーカスできる(実際のDataProviderをテスト対象から外すことが出来る) + +```swift +// Swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +このモックの中で fetchCalled プロパティを定義しています。 fetchCalled は fetch 関数が呼ばれたら true になります。 +これで準備は完了です。 + +このモックを使ってテストをします。このテストで「 ViewController がロードされた時(viewDidLoad)に dataProvider を使って fetch() を実行するか」という動作をテストしています。 + +```swift +// Swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvier = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvier = mockProvier + + expect(mockProvier.fetchCalled).to(equal(false)) + + let _ = viewController.view + + expect(mockProvier.fetchCalled).to(equal(true)) + } + } +} +``` + +このようにオブジェクトのモックを作ることで動作をテストしやすくなります。 + +テストの書き方について、更に詳細を知りたい方はこちらのビデオを参考にしてください。 https://realm.io/jp/news/testing-in-swift/ 。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md new file mode 100644 index 0000000..db389ee --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md @@ -0,0 +1,174 @@ +# Testing OS X and iOS Applications + +*[Xcodeでテストを用意しましょう](SettingUpYourXcodeProject.md)*では Objective-C や Swift の関数やクラスを +テストするために必要なことを述べました。ここでは `UIViewController` のサブクラスなどをテストする際のポイントを述べます。 + +> 関連する LT がありますので[こちら](https://vimeo.com/115671189#t=37m50s)も参考にしてください。 (37'50" から始まる部分です)。 + +## `UIViewController` のライフサイクルイベントを発火させる + +通常は UIKit が view controller のライフサイクルイベントを発火しますが、 +テストをする時は自分たちでライフサイクルイベントを発火させる必要があります。 +呼び出すには3つの方法があります。 + +1. `UIViewController.view`にアクセスする、すると `UIViewController.viewDidLoad()` のイベントが発火します。 +2. `UIViewController.beginAppearanceTransition()` を呼び出すとほとんどのライフサイクルイベントが発火します。。 +3. `UIViewController.viewDidLoad()` や `UIViewController.viewWillAppear()` などのライフサイクルに関わる関数を直接呼び出す。 + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## Storyboard 内に定義した View Controller を初期化する + +Storyboard 内に定義した View Controller を初期化する際は **Storyboard ID** を定義しておく必要があります。 + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +**Storyboard ID** を定義しておくとテストコードから ViewController を初期化することができます。 + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## ボタンをタップされた、などの UIControl Events を発火させる + +ボタンや他の `UIControl` を継承したクラスは Control イベントを発火させる関数を持っています。 +ボタンをタップされた時の動作をテストするにはこのように書くことができます: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md new file mode 100644 index 0000000..095dad3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md @@ -0,0 +1,9 @@ +# トラブルシューティング + +Quick を使用するときによくぶつかる問題の解決策を紹介します。 + +## Cocoapods でインストールした時に「No such module 'Quick'」エラーが出る + +- すでに `pod install` を実行していた場合、一度 Xcode workspace を閉じて再度開いてみてください。それでも解決しない場合は次の手順を試してみてください。 +- `ModuleCache` を含む `~/Library/Developer/Xcode/DerivedData` をすべて削除してください。 +- `Manage Schemes`ダイアログから`Quick`、`Nimble`、`Pods-ProjectNameTests` ターゲットの Scheme が有効なことを確認して、明示的にビルド(`Cmd+B`)をやり直してみてください。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md new file mode 100644 index 0000000..e60967d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md @@ -0,0 +1,203 @@ +# XCTest를 사용한 효과적인 테스트 : Arrange, Act, 그리고 Assert + +XCTest, Quick, 또는 다른 테스트 프레임워크를 사용하는 경우, 간단한 패턴을 따라 효과적인 단위 테스트를 작성할 수 있습니다: + +1. Arrange (환경 구축) +2. Act (실행) +3. Assert (동작 확인) + +## Arrange, Act, and Assert 사용하기 + +예를 들어, `Banana`라는 클래스를 간단히 살펴봅시다: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + + `Banana.peel()` 메서드가 어떻게 되는지 확인해 봅시다: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 간단한 테스트 이름 사용하기 + +이 `testPeel()` 테스트 덕분에 `Banana.peel()` 메소드가 제대로 작동하지 않는다면 즉시 알 수 있습니다. 이는 일반적으로 응용 프로그램 코드가 변경되면서 발생합니다. + +1. 우리는 뜻하지 않게 응용 프로그램 코드를 망가트리므로, 응용 프로그램 코드를 수정해야 합니다. +2. 우리는 응용 프로그램의 작동 방식을 변경했습니다. — 아마도 새로운 기능을 추가했기 때문일 수 있습니다. — 그래서 우리는 테스트 코드를 변경해야 합니다. + +만약 테스트가 실패하기 시작한다면, 위 두 가지 중 어떤 케이스인지 어떻게 알 수 있을까요? 따라서 **테스트의 이름**을 알기 쉬운 것이 중요하다는 사실을 알려줍니다. 좋은 테스트 이름들 : + +1. 무엇을 테스트하고 있는지 명확합니다. +2. 어떤 때 테스트가 통과하거나 실패하는지 명확합니다. + + `testPeel()` 메소드는 좋은 테스트 이름일까요? 더 명확하게 바꾸어 봅시다: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +새로운 이름: + +1. 무엇을 테스트하고 있는지 명확합니다 : `testPeel` 은 `Banana.peel()` 메소드 임을 나타냅니다. +2. 어떤 때 테스트가 통과하거나 실패하는지 명확합니다 : `makesTheBananaEdible` 는 메소드가 호출되면 바나나가 식용 가능한 상태임을 나타냅니다. + +## 테스트 시 조건들 + +`offer()` 함수를 사용해서 사람들에게 바나나를 제공하고 싶다고 가정해 보겠습니다 : + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +우리의 프로그램 코드는 다음 두 가지 중 하나를 수행합니다 : + +1. 이미 벗겨진(먹을 수 있는) 바나나를 제공합니다… +2. …또는 벗겨지지 않은(먹을 수 없는) 바나나를 제공합니다. + +이 두 가지 경우에 대한 테스트를 작성해 봅시다 : + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +테스트 이름은 테스트가 통과해야 하는 **조건**을 명확하게 나타내야 합니다 : 예를 들면 `whenTheBananaIsPeeled`, `offer()` 은 `offersTheBanana` 가 되어야 합니다. 만약 바나나가 벗겨지지 않은 경우라도 우리는 역시 이 경우를 테스트했습니다! + +코드에서 `if` 문 하나에 테스트가 하나씩 가지고 있는 것을 주목해 봅시다. 이것은 테스트를 작성할 때 훌륭한 패턴입니다 : 이 패턴은 모든 조건이 테스트 되는 것을 보장합니다. 이러한 조건 중 하나가 더 이상 작동하지 않거나 변경이 필요 없게 된다면, 우리는 어떤 검사가 필요한지 정확히 알 수 있게 됩니다. + +## `XCTestCase.setUp()` 을 사용하여 간단히 환경구축 하기 + +`OfferTests` 에는 같은 "환경 구축" 코드가 포함되어 있습니다 : 이들은 둘 다 바나나를 만듭니다. 우리는 이 코드를 한 곳에 정리해야 합니다. 왜일까요? + +1. 그대로 두었을 때 `바나나` 생성 방식이 변경되면, 모든 바나나를 만드는 테스트들을 수정해야 합니다. +2. 테스트 코드가 짧아지고 (그리고 **그렇게 만드는 경우에만** ) 테스트의 가독성이 향상됩니다. + +`바나나` 초기화 코드를 모든 테스트 메소드 전에 한 번 실행되는 `XCTestCase.setUp()` 안으로 옮기세요. + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## "환경구축" 코드를 여러 테스트에서 공유하기 + +여러 테스트 간에 동일한 "환경구축" 코드를 사용하는 부분을 발견하면, test target에 'helper 함수'를 정의합시다 : + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 함수를 사용하여 헬퍼를 정의하십시오 : 함수는 서브클래스화 할 수 없으며, 어떤 상태도 유지할 수 없습니다. 서브 클래스화 및 변경 가능한 상태는 당신의 테스트를 읽기 힘들게 합니다. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md new file mode 100644 index 0000000..39dd525 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md @@ -0,0 +1,80 @@ +# 코드를 테스트하지 말고, 동작을 확인하라 + +테스트는 응용프로그램이 **예상치 않은 동작**을 했을 때만 실패하도록 해야 합니다. +응용 프로그램 코드가 *무엇을* 했는지를 테스트하는 것이지, 코드가 *어떻게* 되어있는지를 테스트하는 것이 아닙니다. + +- 응용 프로그램이 *무엇을* 했는지를 확인하는 테스트를 **동작 테스트(behavioral tests)**라고 합니다. +- 동작이 동일하게 유지되더라도 응용 프로그램 코드가 변경되면 중단되는 테스트는 **취약한 테스트 (brittle tests)**입니다. + +우리가 `GorillaDB` 라는 바나나 데이터베이스를 가지고 있다고 가정합시다. +`GorillaDB` 는 key-value로 바나나들을 저장하고 있습니다. 우리는 바바나를 다음과 같이 저장할 수 있습니다 : + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +그리고 나중에 디스크에서 바나나를 이렇게 불러올 수 있습니다 : + +```swift +let banana = database.load(key: "my-banana") +``` + +## 취약한 테스트 (Brittle Tests) + +이 동작을 어떻게 테스트해야 할까요? 한 가지 방법은 바나나를 저장한 이후의 데이터베이스 크기를 확인하는 것입니다 : + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +그러나 `GorillaDB` 의 코드가 변경된다고 상상해 보세요. 바나나를 데이터베이스에서 빠르게 읽을 수 있도록 만들려면 가장 자주 사용되는 바나나의 캐시를 유지해야 합니다. `GorillaDB.size` 의 크기는 캐시가 커짐에 따라 점차 커지고, 테스트는 실패할 것입니다. + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 동작 테스트 (Behavioral Tests) + +동작 테스트 작성의 핵심은 애플리케이션 코드에 기대하는 동작을 명확하게 하는 것입니다. + +`testSave_savesTheBananaToTheDatabase` 라는 테스트에서 : 우리가 바나나를 데이터베이스에 "저장" 할 때 우리가 기대하는 동작은 무엇일까요? "저장"이라는 것은 나중에 읽을 수 있다는 의미입니다. 따라서 데이터베이스의 사이즈가 증가하는 것을 테스트하는 것이 아니라, 바나나를 읽을 수 있는지를 테스트해야 합니다. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +동작 테스트를 작성할 때 중요한 포인트 : + +- 정확히 이 애플리케이션 코드가 무엇을 해야 하는지? +- 테스트가 *오직* 동작만을 테스트하는가? + 또는 코드가 다르게 작동함에 따라 실패할 수 있는가? + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md new file mode 100644 index 0000000..eca7f0d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md @@ -0,0 +1,99 @@ +# Quick의 동작 방식 설정하기 + +`QuickConfiguration` 을 서브클래싱하거나 `QuickConfiguration.Type.configure()` 클래스 메소드를 오버라이드해서 퀵의 동작 방식을 커스터마이징 할 수 있습니다: + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +프로젝트에는 몇 가지 설정이 포함될 수 있습니다. Quick은 이러한 설정이 실행되는 순서에 대해 어떠한 보장을 하지 않습니다. + +## 글로벌 `beforeEach` 와 `afterEach` 클로저 추가하기 + +`QuickConfiguration.beforeEach` 와 `QuickConfiguration.afterEach`를 사용하여 테스트 슈트의 모든 예제 앞이나 뒤에 실행될 클로저를 지정할 수 있습니다 : + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +또한, Quick은 현재 실행 중인 예제와 관련된 메타데이터에 접근하는 것을 허용합니다 : + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md new file mode 100644 index 0000000..0766b77 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md @@ -0,0 +1,25 @@ +# Quick 파일 템플릿 설치하기 + +Quick 레포지토리는 Swift와 Objective-C 사양 모두를 위한 파일 템플릿들을 포함하고 있습니다. + +## Alcatraz + +Quick 템플릿은 Xcode 용 패키지 관리자인 [Alcatraz](https://github.com/supermarin/Alcatraz)를 통해 설치할 수 있습니다. 패키지 매니저 창에서 단지 템플릿을 검색만 하면 됩니다. + + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Rakefile를 통해 수동으로 + +템플릿을 수동으로 설치하려면, 레퍼짓토리를 clone 한 뒤 `templates:install` 명령어를 rake 작업으로 실행하세요. + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +삭제도 간단합니다 : + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md new file mode 100644 index 0000000..8596930 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md @@ -0,0 +1,141 @@ +# Quick 설치하기 + +>시작하기 전에, 어떤 버전의 Quick과 Nimble이 당신의 스위프트 버전에 잘 돌아가는지 [이곳](../../README.md#swift-version)에서 확인하세요. + +Quick은 예제들과 예제 그룹을 정의하는 구문을 제공합니다. Nimble은 `expect(...).to` 라는 주장 구문을 제공합니다. 당신은 둘 중 하나, 또는 두 가지 모두를 테스트에 사용할 수 있습니다. + +여기에 Quick을 테스트에 연결할 수 있는 3가지 권장 방법이 있습니다: + +1. [Git 서브 모듈](#Git-서브-모듈) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift 패키지 매니저 (실험적 기능)](#swift-package-manager) + +하나를 선택하고, 아래 지침을 따르세요. 이를 완료한다면, 당신의 test target의 파일에서 `import Quick`으로 Quick을 불러올 수 있어야 합니다. + +## Git 서브 모듈 + +Git 서브 모듈을 사용하여 Quick과 Nimble을 링크하려면: + +1. Quick 서브 모듈을 추가하세요. +2. `.xcworkspace` 가 프로젝트에 아직 없는 경우, 만드세요. ([방법은 이곳에](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. `Quick.xcodeproj`를 프로젝트의 `.xcworkspace` 에 추가하세요. +4. `Nimble.xcodeproj` 또한 프로젝트의 `.xcworkspace` 에 추가하세요. `path/to/Quick/Externals/Nimble` 에 있습니다. Quick의 종속성에서 Nimble을 추가하면 (하위 모듈에서 바로 추가하는 것과 대조적으로), 당신이 사용하고 있는 Quick의 버전에 맞는 Nimble의 올바른 버전을 사용할 수 있게 됩니다. +5. `Quick.framework`와 `Nimble.framework`를 test target 프로젝트의 "Link Binary with Libraries" build phase에 링크시키세요. + +먼저, Git 서브 모듈을 위한 디렉터리가 없다면, 하나 만드세요. +`Vendor` 라는 이름의 디렉터리가 있다고 가정해보겠습니다. + +**Step 1:** Quick과 Nimble을 Git 서브 모듈에서 다운로드 받으세요: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step 2:** 위에서 다운로드 한 `Quick.xcodeproj` 와 `Nimble.xcodeproj` 파일을 당신의 `.xcworkspace `에 추가하세요. 예를 들어, `Guanaco.xcworkspace`은 Quick과 Nimble을 사용하여 테스트하는 프로젝트의 워크스페이스 입니다. + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step 3:** `Quick.framework` 을 테스트 타겟의`Link Binary with Libraries` build phase에 링크시키세요. 두 개의 `Quick.frameworks` 가 보여야 합니다; macOS용과, iOS용. + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +`Nimble.framework`도 위와 같이 추가하면 끝입니다! + +**서브 모듈 업데이트하기:** Quick이나 Nimble 서브 모듈을 마지막 버전으로 업데이트하기 원한다면, Quick 디렉터리로 들어가서 master 레퍼지토리를 pull 하세요: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +당신의 Git 레퍼지토리는 서브 모듈의 변화를 트래킹할 것입니다. 당신은 Quick 서브 모듈을 업데이트했다는 것을 커밋하기 원할 것입니다. + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Quick 서브 모듈을 포함하는 레퍼지토리를 Clone 하기:** 다른 사람이 당신의 레퍼지토리를 clone 한 후에, 그들은 서브 모듈 또한 pull 해야 할 것입니다. +`git submodule update` 명령어만 실행하면 됩니다: + +```sh +git submodule update --init --recursive +``` + +Git 서브모듈에 대한 자세한 내용은 [여기](http://git-scm.com/book/en/Git-Tools-Submodules)를 참조하세요. + +## CocoaPods + +먼저, 코코아팟의 버전을 0.36.0 이상의 버전으로 업데이트하세요. Swift를 사용하여 코코아팟을 설치하는 데 필요합니다. + +그리고, Quick과 Nimble을 Podfile 에 추가하세요. 또한, ```use_frameworks!```은 코코아팟에서 Swift를 사용하기 데 필요합니다: + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +마지막으로, 다운로드 후에 Quick과 Nimble을 테스트에 추가하세요: + +```sh +pod install +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +Test target에 "Embedded Binaries" 섹션이 없으므로, 타깃의 프레임워크를 복사하기 위해서는 Build Phase의 "Link Binary With Libraries" 와 "Copy Files" 에 추가해야 합니다. + + > Carthage는 동적 프레임워크를 빌드하기 때문에, 유효한 ID 코드 서명 설정이 필요합니다. + +1. [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) 에 Quick을 추가하세요: + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. `carthage update`를 실행합니다. +3. `Carthage/Build/[platform]/` 디렉터리에서, Quick과 Nimble을 test target의 Build Phase에 있는 "Link Binary With Libraries" 에 추가하세요: + ![](http://i.imgur.com/pBkDDk5.png) + +4. 테스트 타겟에 "Copy Files" 유형의 새 빌드 단계를 만들어 주세요: + ![](http://i.imgur.com/jZATIjQ.png) + +5. "Destination"을 "Frameworks"로 설정하고, 두 framework를 모두 추가해주세요: + ![](http://i.imgur.com/rpnyWGH.png) + +Carthage를 사용하여 의존성을 관리하는 것은 "유일한 방법" 이 아닙니다. +더 자세한 내용은 [Carthage 문서](https://github.com/Carthage/Carthage/blob/master/README.md)를 참조하십시오. + +## [Swift 패키지 매니저](https://github.com/apple/swift-package-manager) +[swift.org](https://swift.org) 오픈 소스 프로젝트의 출현과 함께, Swift는 이제 초기지만, 공식적인 패키지 매니저 툴을 제공합니다. 특히, 처음으로 Quick을 비 Apple 플랫폼에서 사용할 수 있다는 가능성을 제공합니다. Swift 패키지 매니저를 사용하여 Quick 테스트 프로젝트를 사용할 수 있도록 초기 단계가 진행되었지만, 툴이 여전히 많이 개발되어 있지 않아 빈번히 파손될 것으로 예상됩니다. + +추가적인 문서가 더 작성될 때까지, 이 레퍼지토리는 어떻게 Quick이 SwiftPM용`Package.swift` 파일에서 종속성으로 선언되는 방법의 예로서 유용할 수 있습니다. + +https://github.com/Quick/QuickOnLinuxExample + +### (권장하지 않는 방법) 실제 iOS 기기에서 Quick Specs를 실행하기 + +Quick on Device로 작성된 Specs를 실행하려면, `Quick.framework`와 +`Nimble.framework`을 `Embedded Binaries`로 테스트 대상의 `Host Application`에 추가해야 합니다. 임베디드 바이너리로 프레임워크를 추가하면, Xcode가 자동으로 프레임워크와 앱을 연결해 줄 것입니다. + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md new file mode 100644 index 0000000..b32fb56 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md @@ -0,0 +1,25 @@ +# 더 많은 리소스 + +## Quick Specs 예제 + +Quick은 [GitHub](https://github.com/github)와 [ReactiveCocoa](https://github.com/ReactiveCocoa)를 포함한 많은 회사와 오픈소스 프로젝트, 그리고 개인이 사용하고 있습니다. 예시를 보려면, 다음을 확인하세요: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## OS X와 iOS 앱 용 유닛 테스트에 대한 추가 정보 + +- **[Quality Coding](http://qualitycoding.org/)**: + 유닛 테스트에 초점을 둔 iOS 개발 관련 블로그 +- **[OCMock Tutorials](http://ocmock.org/support/)**: + 테스트에 가짜 개체가 필요할 때 OCMock를 사용하세요. +- **[Nocilla: iOS와 Mac OS X용 놀라운 Http stubbing](https://github.com/luisobo/Nocilla)**: + 이 라이브러리를 사용하여 인터넷에 요청을 보내고 응답을 받는 코드를 테스트하세요. +- **[Pivotal Labs: Jasmine Custom Matchers로 아름다운 Specs 작성하기 ](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + Nimble에서 사용자 정의 matcher를 작성하는 방법은 [Nimble 문서](https://github.com/Quick/Nimble)를 참조하세요. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md new file mode 100644 index 0000000..c3a11fa --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md @@ -0,0 +1,97 @@ +# Nimble Assertions를 사용하여 테스트를 더욱 간결하게 하기 + +코드가 예상한 대로 작동하지 않을 때, 단위 테스트는 무엇이 문제인가를 **명확하게** 만들어야 합니다. + +원숭이들의 무리가 주어진다면 오직 멍청한 원숭이 무리만 반환하는 함수를 작성해 보세요 : + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +이제 이 함수에 대한 단위 테스트가 있다고 가정을 해 보겠습니다 : + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +테스트는 다음의 실패 메시지와 함께 실패합니다 : + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +실패 했을 때는 많은 정보를 남기는 것이 바람직합니다. 이 실패 메시지의 상태로는 잘 모르겠습니다, "그래, 성공해야 하는데, 무언가가 실패를 했네 — 그래서 뭔데??" 이대로는 우리가 테스트 코드에서 원인을 찾을 때까지 시간을 많이 소비하도록 합니다. + +## 더 나은 오류 메시지, Part 1: 수동으로 `XCTAssert` 실패 메시지 제공하기 + +`XCTAssert` assertions 을 사용하면 사용자 임의 오류 메시지를 지정할 수 있으므로 확실히 도움이 됩니다 : + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +하지만 우리는 오류 메시지를 써야 합니다. + +## 더 나은 오류 메시지, Part 2: Nimble 실패 메시지 + +Nimble은 테스트 assertions를 만들고, 실패 메시지를 읽기 쉽게 만듭니다 : + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +우리는 사용자 임의 실패 메시지를 작성할 필요가 없습니다 — Nimble에서 제공하는 것은 이미 읽기 매우 쉽습니다. + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: VerySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +실패 메시지는 무엇이 잘못되었는지 명확하게 합니다 : 우리는 `silliest()`의 결과에 `kiki` 가 포함될 것으로 예상했지만, 오직 `jane`만 포함하고 있습니다. 이제 무엇이 잘못되었는지 정확히 알고 있으므로 이 이슈를 쉽게 해결할 수 있습니다 : + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble은 많은 다른 assertion을 제공하며, 각각은 큰 실패 메시지를 가지고 있습니다. `XCTAssert` 와는 달리 매번 사용자 임의 실패 메시지를 지정할 필요가 없습니다. + +Nimble assertion의 모든 리스트를 보려면, [Nimble README](https://github.com/Quick/Nimble) 을 확인하세요. +아래는 궁금해하실까 봐 준비한 예제입니다. + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md new file mode 100644 index 0000000..cc5a073 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md @@ -0,0 +1,462 @@ +# Quick Example과 Example그룹으로 구성된 테스트 + +Quick에는 **examples**와 **example groups**를 정의하기 위한 특별한 문법이 있습니다. + +*[XCTest를 사용한 효과적인 테스트 : Arrange, Act, 그리고 Assert](ArrangeActAssert.md)* 에서, +좋은 테스트 메소드 이름을 붙이는 것이 매우 중요하다는 것을 배웠습니다. — 테스트가 실패했을 때, 테스트 이름은 응용 프로그램 코드를 수정할지, 테스트 코드를 업데이트할지를 결정하는 데 중요한 자료가 됩니다. + +Quick examples과 example그룹은 두 가지 용도로 사용됩니다: + +1. 서술적인 테스트 이름을 작성하는 것을 장려합니다. +2. 테스트 "환경 구축" 단계에서 코드를 매우 단순하게 합니다. + +## `it`을 사용한 Examples + + `it` 함수로 정의된 Examples는, 코드가 어떻게 동작하는지를 보여주기 위해 assertions를 사용합니다. 이것들은 XCTest의 테스트 메소드와 같습니다. + +`it`은 example의 이름과 클로저, 두 개의 파라미터가 필요합니다. +아래 example은 `Sea.Dolphin` 클래스가 어떻게 동작하는지를 지정합니다. +새로운 돌고래는 영리하고 친절해야 합니다: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +설명을 사용해서 example이 테스트 중인 내용을 명확하게 하세요. +설명은 어떠한 길이의 아무 문자가 가능하며, 영어 이외로 된 언어나 심지어 이모지를 포함한 모든 문자를 사용할 수 있습니다! :v: :sunglasses: + +## `describe`과 `context`를 사용한 Example그룹 + +Example 그룹은 example의 논리적 그룹입니다. Example 그룹은 설정(setup)과 분해(teardown) 코드를 공유할 수 있습니다. + +### 서술하는 클래스와 `describe`를 사용하는 메소드 + +`Dolphin` 클래스의 `click` 메소드의 동작을 지정하기 위해서는 (다시 말해, 메소드의 동작을 테스트하기 위해서는) 몇 가지 `it` example을 `describe` 함수를 이용해서 그룹화시킬 수 있습니다. 비슷한 example을 그룹화하면 spec을 더 쉽게 읽을 수 있습니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +이 두 가지 example이 Xcode에서 실행되면, `describe` 과 `it` 함수들의 설명이 표시될 겁니다: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +다시 말해, 각각의 example이 테스트하고 있는 것이 명확합니다. + +### `beforeEach` 와 `afterEach`를 사용하여 설정 / 해제코드 공유하기 + +Example groups는 example을 더 명확하게 만들어줄 뿐만 아니라, example 그룹 간에 설정 및 해제 코드를 공유하는 데 유용합니다. + +아래 example에서, `beforeEach` 함수는 그룹에서 각 example 앞에 돌고래와 클릭의 새로운 인스턴스를 생성하는 데 사용되었습니다. +이렇게 하면 모든 example에서 각각은 "신선한" 상태가 되었습니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +이러한 공유 설정이 돌고래 예제에서와 큰 차이가 없는 것처럼 보일 수 있지만, 더 복잡한 객체라면 많은 타이핑을 줄여 줄 것입니다! + +각각의 example *다음에* 코드를 실행하려면 `afterEach`를 사용하세요. + +### `context`를 사용하여 조건부 동작 지정하기 + +돌고래는 반항위치 결정법(박쥐 등이 초음파를 발사하여 위치를 알아내는 일)을 위해 클릭을 사용합니다. 그들이 특히 흥미로운 것에 접근하면, 그것이 무엇인지 알기 위해 일련의 클릭을 하게 됩니다. + +테스트는 `click` 메소드가 다른 상황에서 다르게 동작하는 것을 보여줄 필요가 있습니다. 일반적으로, 돌고래는 한 번만 클릭합니다. 하지만 돌고래가 어떤 흥미로운 것에 접근하게 된다면, 여러 번 클릭할 것입니다. + +이것은 `context` 함수를 이용해서 표현할 수 있습니다: 일반적인 `context`와, 돌고래가 흥미로운 것에 가까이 갔을 때의 `context`입니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +엄밀히 얘기하면, `context` 키워드는 `describe`과 동의어지만, 사려 깊은 사용은 spec을 더 이해하기 쉽게 만들 것입니다. + +### 테스트 가독성: Quick과 XCTest + +[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)에서, +우리는 테스트 당 하나의 조건이 테스트 코드를 구성하는 좋은 방법이라 알아봤습니다. +XCTest에서는, 긴 테스트 메소드 이름을 사용합니다: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Quick을 사용하면, 조건을 더 쉽게 읽을 수 있고, 각 example 그룹에 대해 설정을 할 수 있습니다: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 일시적으로 Example이나 그룹을 비활성화하기 + +일시적으로 통과하지 못한 example이나 example 그룹을 비활성화 시킬 수 있습니다. +Example의 이름은 테스트 결과와 함께 출력되지만, 비활성화된 것들은 출력되지 않을 것입니다. + +example이나 group에 `x`를 추가함으로써 비활성화 시킬 수 있습니다: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 포커스 된 Example의 일정 부분을 임시적 실행하기 + +때로는 오직 하나나 몇 가지 Example 에만 집중하는 것이 도움이 됩니다. 하나 또는 두 가지의 example만 실행하는 것은 전체를 실행하는 것보다 빠릅니다. `fit` 함수를 사용해서 하나 또는 두 개만 실행할 수 있습니다. `fdescribe` 이나 `fcontext`를 사용해서 역시 Example 그룹에 집중할 수 있습니다: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## `beforeSuite` 와 `afterSuite`를 사용하여 전역 설정 / 해제하기 + +어떤 테스트 설정은 실행되기 전에 일부 example이 실행되어야 합니다. 이럴 때, `beforeSuite `와 `afterSuite`를 사용합니다. + +아래의 예제에서는, 모든 example이 실행되기 전에 바다의 모든 생물 데이터베이스가 생성됩니다. 모든 example이 완료되면 데이터베이스는 제거됩니다. + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +`beforeSuite`와 `afterSuite`를 원하는 만큼 지정할 수 있습니다. 모든 +`beforeSuite` 클로저는 테스트가 실행되기 전에 실행되고, 모든 +`afterSuite` 클로저는 모든 테스트가 끝난 뒤에 실행될 것입니다. +이 클로저들이 어떤 순서로 실행될지는 보장되지 않습니다. + +## 현재 Example의 메타데이터에 액세스하기 + +현재 실행되고 있는 example에 대한 이름이나, 지금까지 실행되었던 example의 이름을 알고 싶어하는 경우가 있을 수 있습니다. Quick은 `beforeEach`와 `afterEach` 클로저에서 메타데이터에 대한 액세스를 제공합니다. + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md new file mode 100644 index 0000000..7f96a66 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md @@ -0,0 +1,49 @@ +# Objective-C에서 Quick 사용하기 + +Quick은 Swift와 Objective-C 모두에서 똑같이 잘 작동합니다. + +그러나 Objective-C에서 Quick을 사용할 때 유의해야 할 두 가지를 아래에서 설명합니다. + +## Optional 약식 구문 + +Objective-C 파일에서 Quick을 가져오면, `it`과 `itShouldBehaveLike` 같은 매크로와 `context()` 와 `describe()` 같은 함수들이 정의됩니다. + +만약 테스트 중인 프로젝트에서 이러한 이름을 가진 심볼을 정의한다면, 혼란스러운 빌드 오류를 마주할 수 있습니다. 이럴 때에는, 네임스페이스 충돌을 Quick의 Optional "약식" 구문을 해제함으로 피할 수 있습니다: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +`QUICK_DISABLE_SHORT_SYNTAX` 매크로를 Quick을 헤더에 임포트 하기 전에 정의해야 합니다. + +또한, test target의 build configuration에서 매크로를 정의할 수 있습니다: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## 테스트 타겟에는 적어도 하나의 Swift 파일이 포함되어야 합니다 + +Swift stdlib은 테스트 대상에 연결되지 않으므로, test target에 *적어도 하나의* Swift 파일이 포함되어 있지 않으면 Quick이 제대로 실행되지 않습니다. + +적어도 하나의 Swift 파일이 없으면, 테스트는 다음 오류로 인해 조기 종료될 것입니다: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +문제를 해결하기 위해, `SwiftSpec.swift` 라는 빈 테스트 파일을 test target에 추가하세요: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> 이 이슈에 대한 자세한 내용은 https://github.com/Quick/Quick/issues/164를 참조하세요. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md new file mode 100644 index 0000000..521e83e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md @@ -0,0 +1,35 @@ +# Documentation + +Quick은 당신의 Swift와 Objective-C가 잘 동작하는지 확인할 수 있도록 도와줍니다. 그러나 Quick을 어떻게 사용하는지 아는 것만으로는 효과적인 방법은 아닙니다. 이 가이드는 Quick, XCTest, 또는 다른 테스트 프레임워크를 사용하는 것뿐만 아니라 효과적인 테스트를 작성하는 것을 도와줄 것입니다. + +각 가이드는 특정 주제를 다루고 있습니다. 유닛 테스트에 대한 사전지식이 없는 분이라면, 아래에 소개된 순서대로 읽는 것을 추천해 드립니다. + +- **[Xcode 프로젝트에 Test 설정하기](SettingUpYourXcodeProject.md)**: + 테스트 파일에서 응용 프로그램 코드를 사용하는 데 문제가 있는 경우 읽어보십시오. +- **[XCTest를 사용한 효과적인 테스트 : Arrange (환경구축), Act (실행), 그리고 Assert (동작 확인)](ArrangeActAssert.md)**: + 코드를 더 빠르고 효과적으로 작성하는 데 도움이 되는 `XCTestCase` 테스트를 작성하는 법을 배우려먼 이 글을 읽어보십시오. +- **[코드를 테스트하지 말고, 동작을 확인하라](BehavioralTesting.md)**: + 어떤 테스트가 속도를 높이고, 어떤 테스트가 속도를 낮추는지 배우려면 이 글을 읽어보십시오. +- **[Nimble Assertions를 사용하여 테스트를 더욱 간결하게 하기](NimbleAssertions.md)**: + Nimble을 사용하여 더 나은 실패 메시지를 생성하는 방법을 배우려면 이 글을 읽어보십시오. 더 나은 실패 메시지는 테스트 실패 원인을 파악하는데 걸리는 시간을 줄여주므로 빠르게 대처할 수 있습니다. +- **[Quick Example과 Example 그룹으로 구성된 테스트](QuickExamplesAndGroups.md)**: + Example과 Example 그룹을 사용하여 Quick이 어떻게 더 효과적인 테스트를 도와주는지 배우려면 이 글을 읽어보십시오. +- **[OS X 와 iOS 앱 테스트](TestingApps.md)**: + AppKit과 UIKit 프레임워크를 사용하는 코드 테스팅을 배우려면 이 글을 읽어 보십시오. +- **[test doubles를 사용한 테스트](TestUsingTestDoubles.md)**: + Test Doubles가 무엇인지, 어떻게 사용하는지 배우려면 이 글을 읽어 보십시오. +- **[Shared Assertions를 사용하여 테스트 상용구 줄이기](SharedExamples.md)**: + 테스트들 사이에 assert 집합을 공유하는 방법에 대해 배우려면 이 글을 읽어 보십시오. +- **[Quick의 동작 방식 설정하기](ConfiguringQuick.md)**: + Quick이 테스트를 실행할 때 동작 방식을 바꾸는 법을 배우려면 이 글을 읽어 보십시오. +- **[Objective-C에서 Quick 사용하기](QuickInObjectiveC.md)**: + Objective-C에서 Quick을 사용하는 데 문제가 있으면 이 내용을 읽어 보십시오. +- **[Quick 설치하기](InstallingQuick.md)**: + Git 서브 모듈, CocoaPods, Carthage, 또는 Swift Package Manager를 사용하여 프로젝트에 Quick을 추가하는 법을 읽어 보십시오. +- **[Quick 파일 템플릿 설치하기](InstallingFileTemplates.md)**: + Quick specs를 더 빨리 작성하게 해주는 파일 템플릿을 설치하는 방법을 배우려면 이 글을 읽어 보십시오. +- **[더 많은 리소스](MoreResources.md)**: + OS X와 iOS 테스트에 대한 추가 리소스 목록입니다. +- **[일반적인 설치 이슈들](Troubleshooting.md)**: + 다른 문제가 발생한다면 이 글을 읽어 보십시오. + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..518e5fa --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md @@ -0,0 +1,80 @@ +# Xcode 프로젝트에 Test 설정하기 + +Xcode7에서는 Command Line Tool 프로젝트 유형을 제외하고 새 프로젝트를 만들면, 기본적으로 Unit test target이 포함됩니다. [Command Line Tool 프로젝트에 대한 특정 지시사항 보기](#Command-Line-Tool-프로젝트에서-테스트-타겟-설정하기). 단위 테스트를 작성하려면, 필수적으로 Unit test target에서 Main target 코드를 사용할 수 있어야 합니다. + +## Swift 코드를 Swift에서 테스트하기 + +Swift로 작성된 코드를 테스트하려면 다음 두 가지 작업을 수행해야 합니다. + +1. `.xcodeproj` 에서 "Defines Module"을 `YES`로 설정하십시오. + + * Xcode에서 하려면: 프로젝트를 선택하고, "Build Settings"의 "Packaging" 헤더에서, + "Defines Module" 라인을 "Yes"로 선택하세요. 참고: "Packaging" 섹션을 보려면 Build Settings를 "Basic" 대신 "All"로 선택해야 합니다. + +2. `@testable import YourAppModuleName` 을 당신의 유닛테스트에 포함하세요. 그러면 `Public`과 `internal` (기본) 기호가 당신의 테스트에 표시될 것입니다. `private` 기호는 아직 사용할 수 없습니다. + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Xcode Test Navigator의 Quick과의 통합에는 몇 가지 제약 사항이 있습니다. (open [issue](https://github.com/Quick/Quick/issues/219)). Quick 테스트는 실행될 때까지 내이게이터에 표시되지 않을 것이며, 반복 실행은 예측할 수 없는 방향으로 목록을 재설정하는 경향이 있으며, 테스트는 소스 코드 옆에 표시되지 않습니다. +> 레이더를 Apple에 제출하고, Apple 엔지니어에게 이 기능 요구를 홍보하기 위해 [rdar://26152293](http://openradar.appspot.com/radar?id=4974047628623872)을 언급하세요. + +> 일부 개발자는 Swift 소스 파일을 test target으로 추가할 것을 권장합니다. +> 하지만 이는 [미묘하고, 오류를 진단하기 어려워지므로](https://github.com/Quick/Quick/issues/91), 권장 사항은 아닙니다. + +## Objective-C 코드를 Swift에서 테스트하기 + +1. Bridging header를 Test target에 추가하세요. +2. Bridging header에서, 테스트 해야 할 코드가 있는 파일을 불러옵니다. + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +이제 Swift 테스트 파일에서 `MyClass.h` 에 있는 코드를 사용할 수 있습니다. + +## Swift 코드를 Objective-C에서 테스트하기 + +1. `@objc` 속성을 사용하여 Objective-C로 테스트하려는 Swift 클래스와 함수를 연결합니다. +2. 당신의 단위 테스트에서 모듈의 Swift 헤더들을 불러옵니다. + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Objective-C 에서 Objective-C 코드를 테스트하기 + +Test target에서 테스트하려는 코드가 정의된 파일을 불러옵니다. + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### Command Line Tool 프로젝트에서 테스트 타겟 설정하기 + +1. 프로젝트 창에서 대상을 프로젝트에 추가합니다. +2. "OS X Unit Testing Bundle"을 선택합니다. +3. 주요 타깃의 스키마를 편집합니다. +4. "Test" 를 선택하고, "Info" 머리말 아래 있는 "+"를 클릭한 뒤, 당신의 테스트 번들을 선택하세요. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md new file mode 100644 index 0000000..ebc1c9a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md @@ -0,0 +1,116 @@ +# Shared Assertions를 사용하여 테스트 상용구 줄이기 + +때에 따라, 같은 명세서가 여러 객체에 적용될 수 있습니다. + +예를 들어, `Edible`이라는 프로토콜을 생각해 보자. 돌고래가 `Edible` 한 (먹을 수 있는) 음식을 먹으면 돌고래는 행복해집니다. `Mackerel`(고등어) 와 +`Cod`(대구)는 모두 먹을 수 있습니다. Quick은 돌고래가 어느 쪽을 먹어도 기쁘다는 것을 쉽게 테스트할 수 있게 합니다. + +아래 예제는 "먹을 수 있는 것" 에 대한 "공유 명세"를 정의하고, 고등어와 대구가 모두 "먹을 수 있는 것"처럼 행동하도록 지정합니다: + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +공유된 예제들은 임의 개수의 `it`, `context`, `describe` 블록이 포함될 수 있습니다. 이들은 여러 다른 객체에 대해 같은 테스트를 실행할 때 많은 타이핑을 절약할 수 있습니다. + +어떤 경우에는, 추가 컨텍스트가 필요하지 않습니다. Swift에서는, 어떤 매개변수도 사용하지 않는 `sharedExamples` 클로저를 사용할 수 있습니다. 이것은 일종의 전역 상태의 어떤 테스트를 할 때 유용할 수 있습니다: + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Objective-C에서는, 해당 인수를 사용할 계획이 없더라도, `QCKDSLSharedExampleContext`를 사용하는 블록을 전달해야 합니다. 미안하지만, 이것이 쿠키를 부수는 방식이다! +> :cookie: :bomb: + +역시나 `fitBehavesLike` 함수를 이용해서 공유 예제를 "집중" 할 수 있습니다. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md new file mode 100644 index 0000000..682288a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md @@ -0,0 +1,129 @@ +# Mocks 테스트 (모의 테스트) + +## Test doubles + +객체 간 종속성으로 인해 테스트를 작성할 때 문제가 발생할 수 있습니다. 예를 들어, `Tire`에 의존하거나 사용하는 `Car` 클래스가 있다고 가정해봅시다. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests`는 `Tire`라고 불리는 `Car`를 테스트합니다. 이제 `Tire`의 버그로 인해 `CarTests`가 실패할 수 있습니다. (`Car`는 괜찮습니다) 이는 "무엇이 망가졌는가?" 라는 질문에 대답하기 어려울 수 있습니다. + +이러한 문제를 피하려면, `CarTests`의 `Tire` 용 stand-in 객체를 사용할 수 있습니다. 이런 경우, `PerfectTire`라는 `Tire` 용 stand-in 객체를 만듭니다. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` 는 `Tire` 와 모두 동일한 public 함수와 프로퍼티를 가질 겁니다. 하지만, 이러한 일부 또는 전체의 함수 또는 프로퍼티에 대한 구현은 다를 수 있습니다. + +`PerfectTire` 와 같은 객체는 "test doubles"로 불립니다. Test doubles는 관련 객체의 기능을 독립적으로 테스트하기 위한 "stand-in objects"로 사용됩니다. 여기 몇 가지 종류의 test doubles가 있습니다: + +- Mock 객체: 테스트 객체에서 결과물을 받기 위해 사용됩니다. +- Stub 객체:테스트 객체의 입력을 제공하는 데 사용됩니다. +- Fake 객체: 원래 클래스와 비슷하지만, 단순화된 방식으로 작동합니다. + +Mock 객체의 사용법부터 알아봅시다. + +## Mock + +Mock 객체는 다른 객체와의 정확한 상호 작용을 열거하고, 무언가가 잘못되었을 때를 감지하는 데 초점을 둡니다. Mock 객체는 테스트가 진행되는 도중에 호출되어야 하는 메소드와 mock 객체가 반환해야 하는 값을 (미리) 알아야 합니다. + +Mock 객체는 다음과 같은 이유로 훌륭합니다: + +- 훨씬 더 빨리 테스트합니다. +- 인터넷에 연결되어 있지 않은 경우에도 테스트를 실행합니다. +- 클래스를 종속성과 분리하여 테스트하는 데 중점을 둡니다. + +### Swift에서 Mock 객체로 테스트 작성하기 + +#### Sample app + +예를 들어, 인터넷에서 데이터를 검색하는 앱을 만들어 봅시다: + +* 인터넷의 데이터는 `ViewController`에 표시되어야 합니다. +* 사용자 정의 클래스는 데이터를 가져오는 메서드를 지정하는 `DataProviderProtocol`을 상속합니다. + +`DataProviderProtocol` 은 다음과 같이 정의됩니다: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` 는 인터넷에서 데이터를 가져와 `callback` 클로저를 사용하여 데이터를 반환합니다. + +다음은, `DataProviderProtocol` 프로토콜을 따르는 `DataProvider`클래스 입니다. + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = URL(string: "http://example.com/")! + let session = URLSession(configuration: .default) + let task = session.dataTask(with: url) { + (data, resp, err) in + let string = String(data: data!, encoding: .utf8) + callback(data: string) + } + task.resume() + } +} +``` + +이 시나리오에서, `fetch()` 는 `ViewController` 의 `viewDidLoad()` 메소드에서 호출됩니다. + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### `DataProviderProtocol`의 Mock을 사용하여 테스트 + +`ViewController` 는 `DataProviderProtocol`을 신뢰합니다. 뷰 컨트롤러를 독립적으로 테스트하려면, `DataProviderProtocol` 을 따르는 mock 객체를 만들 수 있습니다. + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + + `fetch()` 가 호출되면, `fetchCalled` 프로퍼티가 `true`로 설정되어, 테스트에서 호출되었음을 확인할 수 있습니다. + +다음 테스트에서는 `ViewController` 가 로드될 때, `dataProvider.fetch() `를 호출하는지 확인합니다. + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvider = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvider = mockProvider + + expect(mockProvider.fetchCalled).to(beFalse()) + + let _ = viewController.view + + expect(mockProvider.fetchCalled).to(beTrue()) + } + } +} +``` + +테스트를 작성하는 것에 관해 관심이 있어서 더 배우고 싶다면, 다음을 참조하세요. . diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md new file mode 100644 index 0000000..c6df101 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md @@ -0,0 +1,173 @@ +# OS X 와 iOS 앱 테스트 + +*[Xcode 프로젝트에 Test 설정하기](SettingUpYourXcodeProject.md)* +Objective-C 또는 Swift 함수와 클래스를 테스트하기 위해 알아야 할 모든 것을 다룹니다. +이 섹션에서는, `UIViewController` 하위 클래스와 같은 클래스를 테스트하기 위한 몇 가지 추가적인 힌트를 살펴 보겠습니다. + +> 이 주제들을 다루는 라이트닝 토크를 [이곳](https://vimeo.com/115671189#t=37m50s)에서 볼 수 있습니다. (37분 50초쯤 시작합니다) + +## `UIViewController` 라이프 사이클 이벤트 트리거 + +일반적으로, UIKit은 뷰 컨트롤러의 라이프사이클 이벤트를 앱 내에서 표시할 때 트리거합니다. 그러나, `UIViewController`가 테스트 될 때, 이러한 `UIViewController`를 직접 트리거해야 합니다. 다음 3가지 방법 중 하나로 할 수 있습니다: + +1. `UIViewController.viewDidLoad()` 같은 것을 트리거하는 `UIViewController.view`에 액세스하기. +2. `UIViewController.beginAppearanceTransition()` 을 사용하여 대부분의 라이프사이클 이벤트를 트리거하기. +3. `UIViewController.viewDidLoad()` 또는 `UIViewController.viewWillAppear()` 와 같은 메서드를 직접 호출하기. + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## 스토리보드에 정의된 뷰 컨트롤러를 초기화하기 + +스토리보드에 정의된 뷰 컨트롤러를 초기화하기 위해서는, **Storyboard ID**를 뷰 컨트롤러에 지정해야 합니다: + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +그렇게 하면, 테스트 내에서 뷰 컨트롤러를 인스턴스화 할 수 있습니다: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## Button 탭과 같은 UIControl 이벤트 트리거 + +버튼과 다른 UIKit 클래스는 버튼 탭과 같이 프로그래밍적인 방법으로 컨트롤 이벤트를 보낼 수 있는 메소드를 정의하는 `UIControl`을 상속합니다. +버튼을 누를 때 발생하는 동작을 테스트하려면 다음과 같이 작성할 수 있습니다: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md new file mode 100644 index 0000000..e85b4c2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md @@ -0,0 +1,10 @@ +# 일반적인 설치 이슈들 + +다음은 framework를 사용할 때 나타나는 일반적인 문제에 대한 해결책입니다. + +## No such module 'Quick' + +- 이미 `pod install`을 실행한 경우, Xcode workspace를 닫았다가 다시 열어주세요. 그래도 문제가 해결되지 않는다면, 다음을 계속하세요. +- _폴더 전체_ `~/Library/Developer/Xcode/DerivedData`를 삭제합니다. 여기에는 `ModuleCache` 가 포함됩니다. +- Scheme 관리 창에서 scheme을 활성화한 후, `Quick`, `Nimble` 그리고 `Pods-ProjectNameTests` 타깃을 명시적으로 빌드 (`Cmd+B`) 합니다. + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md new file mode 100644 index 0000000..4e41676 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md @@ -0,0 +1,78 @@ +# Não Teste o Código, Verifique Comportamento + +Testes devem falhar somente se a aplicação **se comportar diferente**. +Eles devem testar *o que* o código da aplicação faz, não *como* faz. + +- Testes que verificam *o que* a aplicação faz são **testes de comportamento**. +- Testes que quebram se o código da aplicação muda, mesmo que o comportamento seja mantido, são **teste frágeis**. + +Vamos supor que temos uma database de bananas, chamada `GorillaDB`. +`GorillaDB` é uma database baseada em chave-valor que guarda bananas. Nós podemos salvar bananas: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +E podemos ler bananas: + +```swift +let banana = database.load(key: "my-banana") +``` + +## Testes Frágeis + +Como podemos testar esse comportamento? Um jeito seria checar o tamanho da database depois de salvar uma banana: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +Imagine, no entanto, que o código fonte da `GorillaDB` mude. Para que a operação de leitura de bananas da database seja mais rápida, é mantido um cache com as bananas lidas com maior frequência. `GorillaDB.size` aumenta conforme o tamanho do cache aumenta, e nosso teste falha: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## Testes de Comportamento + +O segredo para escrever testes de comportamento é determinar exatamente o que se espera que o código da aplicação faça. + +No contexto do teste `testSave_savesTheBananaToTheDatabase`: qual é o comportamento esperado quando uma banana é salva na database? "Salvar" implica que essa banana pode ser lida mais tarde. Então, ao invés de testar que o tamanho da database aumenta, nós devemos testar que é possível ler uma banana. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +O segredo para escrever testes de comportamento é perguntar: + +- O que exatamente o código dessa aplicação deve fazer? +- O meu teste está verificando *apenas* esse comportamento? Ou o teste pode falhar devido à forma como o código funciona? \ No newline at end of file diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/README.md new file mode 100644 index 0000000..c170942 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/README.md @@ -0,0 +1,39 @@ +# Documentação + +Quick te ajuda a verificar como programas em Swift e Objective-C se comportam. + +Fazê-lo de forma eficaz não é apenas questão de saber como usar Quick. Os guias nesse diretório podem te ajudar a escrever testes eficazes --não apenas usando Quick, mas até mesmo XCTest ou outros framework de teste. + +Cada guia cobre um tópico em particular. Se você é completamente novo a teste unitário, considere lê-los na ordem que são introduzidos abaixo: + +- **[Configurar Testes no seu Xcode Project](SettingUpYourXcodeProject.md)**: + Leia isto se você esta com problemas para usar o código da sua aplicação de dentro dos seus arquivos de teste. +- **[Testes Eficazes Usando XCTest: Arrange, Act e Assert](ArrangeActAssert.md)**: + Leia isto para aprender como escrever `XCTestcase` testes que o ajudarão a escrever código mais rápido e mais eficaz. +- **[Não Teste o Código, Verifique Comportamento](BehavioralTesting.md)**: + Leia isto para aprender que tipos de testes te deixam mais rápido e quais os que só vão acabar te deixando mais devagar. +- **[Testes Limpos Usando Nimble Assertions](NimbleAssertions.md)**: + Leia isto para aprender a usar Nimble para gerar melhores mensagens de falha. + Melhores mensagens de falha ajudam a se mover mais rápido, gastando menos tempo tentando descobrir por que +    um teste falhou. +- **[Testes Organizados com Exemplos Quick e Grupos de Exemplo](QuickExamplesAndGroups.md)**: + Leia isto para aprender como Quick pode ajudar ainda mais a escrever testes eficazes, usando *exemplos* e *grupos de exemplos* +- **[Testando Aplicações OS X e iOS](TestingApps.md)**: + Leia isto para aprender mais sobre testar código que utiliza + AppKit e UIKit frameworks. +- **[Testando com testes dublês](TestUsingTestDoubles.md)**: + Leia isto para aprender o que são testes dublês e como usa-lôs. +- **[Reduzindo Teste Boilerplate com Assertions Compartilhados](SharedExamples.md)**: + Leia isto para aprender como compartilhar conjuntos de assertions entre seus testes. +- **[Configurando como Quick se Comporta](ConfiguringQuick.md)**: + Leia isto para aprender como você pode mudar como Quick se comporta quando roda os sua suite de testes. +- **[Usando Quick com Objective-C](QuickInObjectiveC.md)**: + Leia isto se você esta com problemas para usar Quick em Objective-C. +- **[Instalando Quick](InstallingQuick.md)**: + Leia isto para instruções de como adicionar Quick no seu projeto, usando Git submodules, CocoaPods, Carthage, ou Swift Package Manager. +- **[Instalando Arquivos Templates Quick](InstallingFileTemplates.md)**: +Leia isto para aprender como instalar arquivos templates que deixam escrever Quick specs mais rápidos. +- **[Mais Recursos](MoreResources.md)**: + Uma lista de recursos adicionais sobre testes OS X e iOS. +- **[Troubleshooting](Troubleshooting.md)**: + Leia isto quando você tiver outros problemas. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md new file mode 100644 index 0000000..eabde35 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md @@ -0,0 +1,116 @@ +# Reduzindo Teste Boilerplate com Assertions Compartilhados + +Em alguns casos, o mesmo conjunto de especificações se aplica a múltiplos objetos. + +Por exemplo, considere um protocol chamado `Edible` (comestível). Quando um golfinho come algo `Edible`, ele fica feliz. `Mackerel` (um tipo de peixe) e `Cod` (bacalhau) são comestíveis. Quick permite testar facilmente que um golfinho fica feliz quando come qualquer um desses peixes. + +O exemplo abaixo define um conjunto de "exemplos compartilhados" para "algo comestível", e especifica que tanto `Mackerel` quanto `Cod` se comportam como "algo comestível": + + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Exemplos compartilhados podem incluir qualquer número de blocos `it`, `context` e `describe`. Isso economiza *muito* quando deve-se escrever os mesmos testes para diferentes objetos. + +Em alguns casos, nenhum `context` adicional é necessário. Em Swift, é possível usar `sharedExamples` closures que não recebem parâmetros. Isso pode ser útil quando se esta algum estado global: + + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Em Objective-C, é necessário passar um bloco que recebe um `QCKDSLSharedExampleContext`, mesmo se esse argumento não for usado. Desculpe, mas é assim que a banda toca! :trumpet: :notes: + +Também é possível "focar" exemplos compartilhados usando a função `fitBehavesLike`. \ No newline at end of file diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md new file mode 100644 index 0000000..fda4f8a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md @@ -0,0 +1,205 @@ +# 编写高效的 XCTest 测试: Arrange,Act 和 Assert + +当你使用 XCTest,Quick 或者其他测试框架时,你可以遵循下面的模式来编写有效的单元测试: + +1. Arrange - 安排好所有先要条件和输入 +2. Act - 对要测试的对象或方法进行演绎 +3. Assert - 作出预测结果的断言 + +## Arrange, Act, and Assert 三部曲 + +举个例子,假设现在有一个叫 `Banana` 的类: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +现在我们想验证一下 `Banana.peel()` 方法的行为是否跟我们设想的一样: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 使用明确清晰的方法名字 + +我们的 `testPeel()` 函数可以确保如果 `Banana.peel()` 方法出了问题,我们可以第一时间知道。这通常发生在我们修改了应用的代码后,同时也意味着: + +1. 如果我们意外地写错了代码,我们需要修复它从而让代码正常工作。 +2. 或者我们可能为了增加一个新的功能而改变原有的代码 —— 因此我们需要更改现有的测试代码。 + +如果我们的测试开始出现失败,怎么才能知道是哪一个测试用例失败呢?这可能会让你吃惊,最好的办法是从 **测试方法的名字** 找出端倪。好的测试方法会: + +1. 明确什么是对正在被测试的对象。 +2. 明确什么时候测试应该通过,什么时候测试应该失败。 + +那我们上面的 `testPeel()` 方法的命名清晰吗?我们可以让它变得更清晰: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +新的方法命名: + +1. 明确了什么是正在被测试的对象:`testPeel` 指明了正在被测试的是 `Banana.peel()` 方法。 +2. 明确了测试通过的条件:`makesTheBananaEdible` 指明了只要这个测试方法被调用后,香蕉就已经被剥皮(可食用)。 + +## 对条件进行测试 + +假设我们现在可以向别人提供香蕉,有这样一个叫 `offer()` 的函数: + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +我们的代码做了以下其中一件事: + +1. 给别人一个已经被剥过皮的香蕉。 +2. 或者给别人一个没剥皮的香蕉。 + +现在让我们为这两种情况编写测试: + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +我们的方法名字清晰地指明了测试通过时所应具备的**条件**:在 `whenTheBananaIsPeeled` 测试中,`offer()` 方法应该 `offersTheBanana`。那香蕉没被剥皮的情况呢?好吧,我们也写了另外一个测试来测试这种情况。 + +注意,我们为每个 `if` 条件单独写了一个测试。在我们写测试时,确保每个条件都能被测试,是一个好的模式。如果其中一个条件不再满足,或者需要修改,我们就很容易知道哪个测试需要处理。 + +## 用 `XCTestCase.setUp()` 来编写更简洁的 "Arrange" + +我们的两个 `OfferTests` 测试都包含了相同的 "Arrange" 代码:他们都初始化了一个香蕉。我们应该把初始化方法移到一个单独的地方。为什么? + +1. 现在,假设需要修改 `Banana` 的初始化方法,那么我们就要对每个方法进行修改。 +2. 我们的测试方法会更加简洁 —— 这对于我们是一件好事,当且**仅当**测试方法能更容易被人阅读的时候。 + +现在我们把 `Banana` 的初始化方法移到 `XCTestCase.setUp()` 方法里,这样当每个测试开始时,初始化方法都会被调用。 + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## 在不同的测试里共享 "Arrange" 代码 + +如果你发现你在很多地方都有相同重复的 "arrange" 方法,你可能想定义一个通用的 helper 函数: + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 用一个通用函数来定义那些不能被抽象,或不会保存状态的方法。抽象的子类和可修改的状态会使你的测试难以阅读。 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md new file mode 100644 index 0000000..70a0b51 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md @@ -0,0 +1,75 @@ +# 别测试代码,而应该验证程序的行为 + +测试应该只在程序的**行为和预期的不一样**时,才不通过。测试应该测试程序的代码做了什么,而不是测试程序如何实现。 + +- 验证应用程序做了什么的,叫做**行为测试**。 +- 即使应用程序的行为不发生变化,只要应用程序的代码发生了变化,测试就不通过的,叫做**脆性测试**。 + +假设我们有一个香蕉数据库,叫做 `GorillaDB`。`GorillaDB` 是一个以键-值对来储存香蕉的数据库。我们可以用这样的方式储存香蕉: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +之后可以从数据库里取回香蕉: + +```swift +let banana = database.load(key: "my-banana") +``` + +## 脆性测试 + +我们如何测试这个存取的行为呢?一种方式是每当我们储存一根香蕉后就检查数据库的大小: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { +// Arrange: Create a database and get its original size. +let database = GorillaDB() +let originalSize = database.size + +// Act: Save a banana to the database. +let banana = Banana() +database.save(banana: banana, key: "test-banana") + +// Assert: The size of the database should have increased by one. +XCTAssertEqual(database.size, originalSize + 1) +} +``` + +然而,设想一下 `GorillaDB` 的源代码发生了变化。为了从数据库里更快地取出香蕉,数据库预留了一部份缓存空间用于存放经常使用的香蕉。`GorillaDB.size` 就会随着缓存的增加而增加,这样我们的测试就不能通过了: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 行为测试 + +编写行为测试的关键,就是准确的定位你想让你的程序代码做什么。 + +在我们的 `testSave_savesTheBananaToTheDatabase` 的测试中:当我们在数据库中储存一根香蕉时,我们所希望程序完成的是一个怎样的行为呢?应该是保存香蕉,即之后可以取回香蕉。因此,我们不该测试数据库大小的增加,而应该测试我们能不能从数据库里取回香蕉。 + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { +// Arrange: Create a database and get its original size. +let database = GorillaDB() +- let originalSize = database.size + +// Act: Save a banana to the database. +let banana = Banana() +database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +编写行为测试的关键,就在于思考这些问题: + +- 这段程序代码是用来做什么的? +- 我的测试只验证了程序的行为吗?它可能因为代码运行的其他原因而不通过吗? diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md new file mode 100644 index 0000000..fc5ba90 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md @@ -0,0 +1,102 @@ +# 配置 Quick 的行为 + +你可以通过继承 `QuickConfiguration` 并且 +重写 `QuickConfiguration.Type.configure()` 类方法的方式来自定义 Quick 的行为。 + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +一个项目可能包含多个配置。Quick 不保证这些配置执行的先后顺序。 + +## 添加全局闭包 `beforeEach` 和 `afterEach` + +你可以通过使用 `QuickConfiguration.beforeEach` 和 `QuickConfiguration.afterEach` ,执行测试中每个例子运行前或运行后特定的闭包代码: + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +另外,Quick 允许你根据当前正在运行的例子,访问元数据: + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md new file mode 100644 index 0000000..7e35365 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md @@ -0,0 +1,26 @@ +# 安装 Quick 文件模板 + +Quick 仓库包含了 Swift 和 Objective-C 规范的文件模板。 + +## Alcatraz + +Quick 模板可以通过 [Alcatraz](https://github.com/supermarin/Alcatraz) 安装,这是一个 Xcode 的包管理器。只需在包管理器里搜索 Quick : + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## 使用 Rakefile 手动安装 + +如果想手动安装模板,那么只需克隆仓库并运行 rake 命令 `templates:install` : + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +若要卸载模板,可以运行命令: + +```sh +$ rake templates:uninstall +``` + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md new file mode 100644 index 0000000..2f54b0a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md @@ -0,0 +1,157 @@ +# 安装 Quick + +> **如果你的 Xcode 版本是7.1,** 请使用新的 Quick--`v0.9.0` 写测试代码。 +> 新发布的版本是基于 `swift-2.0` 这个分支开发的。 + + + +Quick 提供了定义例子和例子群的语法。 Nimble 提供了如 `expect(...).to` 的断言语法。 在写测试代码的时候,你可以使用它们中的任意一个或者同时使用它们。 + +下面是几种主要的方法,用来添加 Quick 支持: + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift Package Manager (experimental)](#swift-package-manager) + +你可以选择其中一种方法,并按照下面的步骤进行。完成之后,就可以通过 `import Quick` 使你的测试支持 Quick 。 + +## Git Submodules + +通过以下步骤可以使用 Git 的子模块(submodules) 为项目添加 Quick 和 Nimble : + +1. 添加子模块 Quick。 +2. 为你的项目新建一个 `.xcworkspace` 文件,如果原本已经有这个文件,则跳过此步骤。 ([如何添加请看这里](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. 把 `Quick.xcodeproj` 添加到项目的 `.xcworkspace`中。 +4. 把 `Nimble.xcodeproj` 添加到项目的 `.xcworkspace`中。它所在的目录是: `path/to/Quick/Externals/Nimble`。 通过从 Quick 的依赖库中添加 Nimble (而不是直接添加为子模块),可以确保无论所用的 Quick 是什么版本,都能使用正确版本的 Nimble 。 +5. 把 `Quick.framework` 和 `Nimble.framework` 添加到项目 "build phase" 选项页的 "Link Binary with Libraries" 列表中。 + +首先,你需要有一个 Git 子模块的目录,如果没有的话,就创建一个。假设这个目录的名称是 "Vendor" 。 + +**第一步:** 下载 Quick 和 Nimble 作为 Git 的子模块: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**第二步:** 把下载完的 `Quick.xcodeproj` 和 `Nimble.xcodeproj` 文件添加到项目的 `.xcworkspace` 上。 例如:下图是 `Guanaco.xcworkspace` 已经添加了 Quick 和 Nimble : + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**第三步:** 把 `Quick.framework` 添加到测试目标(target)的 `Link Binary with Libraries` 列表中。你会发现有两个 `Quick.frameworks`;其中一个是 OS X 平台的,另一个是 iOS 平台的。 + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +重复上面的步骤,添加 `Nimble.framework`。 + +**更新子模块:** 如果你想把 Quick 和 Nimble 模块升级到最新版本,你可以在 Quick 目录下使用 `pull` 来更新,如下: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +你的 Git 仓库会自动同步更改到子模块中。如果你想确保已经更新了 Quick 子模块,那么可以这样: + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**克隆一个包含有 Quick 子模块的仓库:** 当其他人克隆了你的仓库后,他们会同时拥有这些子模块。 +他们可以运行 `git submodule update` 命令: + +```sh +git submodule update --init --recursive +``` + +更多关于子模块的内容,可以参考[这里](http://git-scm.com/book/en/Git-Tools-Submodules)。 + +## CocoaPods + +首先,请把 CocoaPods 升级到0.36或者更高的版本,这样才能在 Swift 下使用 CocoaPods 。 + +然后在你的 Podfile 中添加 Quick 和 Nimble 。并且为了在 Swift 中使用 CocoaPods ,记得加上这一行: ```use_frameworks!``` 。 + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +最后,下载并将 Quick 和 Nimble 导入到你的测试中: + +```sh +pod install +``` + +### 使用 Swift 1.2 ? + +最近发布的 Quick (0.4.0) 适用于 Swift 2 (Xcode 7),但是 Nimble (1.0.0) 适用于 Swift 1.2 (Xcode 6)。 + +如果你想在 Xcode 6 中使用它们,请使用以下这段代码: + +```sh +target 'MyTests' do + use_frameworks! + pod 'Quick', '~>0.3.0' + pod 'Nimble', '~>1.0.0' +end +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +在一个项目中,测试所在的目标(target)并没有 "Embedded Binaries" 这部分内容, 因此必须把框架添加到目标的 "Link Binary With Libraries" 里,并且在 build phase 选项页中新建一条 "Copy Files" 把它们复制到目标的框架列表中。 + + > 因为 Carthage 生成的是动态的框架,所以你需要有一个合法的身份标识。 + +1. 在 [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) 中添加 Quick ,如下: + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. 运行 `carthage update`。 +3. 从 `Carthage/Build/[platform]/` 目录下, 找到 Quick 框架和 Nimble 框架,把它们添加到测试目标的 "Link Binary With Libraries" 列表中: + ![](http://i.imgur.com/pBkDDk5.png) + +4. 在你的测试目标下新建一条 "Copy Files" : + ![](http://i.imgur.com/jZATIjQ.png) + +5. 将 "Destination" 设为 "Frameworks",然后添加这两个框架: + ![](http://i.imgur.com/rpnyWGH.png) + +注意,这并不是使用 Carthage 来管理依赖的唯一方法。更多的方法请参考 [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md)。 + +## [Swift Package Manager](https://github.com/apple/swift-package-manager) +随着 [swift.org](https://swift.org) 上一个开源项目的出现, Swift 现在有了一个官方的包管理器。 尽管它刚问世不久,但是它首次使在非苹果平台上使用 Quick 成为了可能。经过初期的开发,现在已经可以利用 Swift Package Manager 为测试项目添加 Quick 支持了。但是由于这个包管理器正在开发中,在使用的过程中可能会出现一些问题。 + +在更新的帮助文档发布之前,这个项目阐述了如何在 SwiftPM 的 `Package.swift` 中添加 Quick 。 + +https://github.com/Quick/QuickOnLinuxExample + +### (不建议) 在真实的iOS设备上运行用Quick书写的代码 + +为了在设备上运行 Quick 形式的代码,你需要把 `Quick.framework` 和 `Nimble.framework` 作为 `Embedded Binaries` 添加到项目目标的 `Host Application` 里。 当以二进制文件的形式把框架添加到 Xcode 中,Xcode 会自动为 App 添加 Quick 框架。 + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md new file mode 100644 index 0000000..0a9ed84 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md @@ -0,0 +1,23 @@ +# 更多资源 + +## Quick Specs 的例子 + +很多公司、开源项目和独立开发者都使用了 Quick ,包括 [GitHub](https://github.com/github) 和 [ReactiveCocoa](https://github.com/ReactiveCocoa)。具体例子请参考以下链接: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## 关于 OS X 和 iOS 应用单元测试的更多信息 + +- **[Quality Coding](http://qualitycoding.org/)**:一个关注单元测试的 iOS 开发博客。 +- **[OCMock Tutorials](http://ocmock.org/support/)**:当你需要在测试中使用伪对象时,使用 OCMock 。 +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**:使用这个库来测试那些与互联网进行数据交换的代码。 +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**:参考 [the Nimble documentation](https://github.com/Quick/Nimble) ,了解如何用 Nimble 编写自定义的匹配器。 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md new file mode 100644 index 0000000..a1b0197 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md @@ -0,0 +1,100 @@ +# 使用 Nimble 断言,让测试更清晰 + +当代码不能如预期那样正常运行时,单元测试应该能够反映出问题的所在。 + +例如,下面这个函数能够从所给的一组猴子中筛选并返回其中的傻猴子: + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +现在有一个针对这个函数的单元测试: + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +这个测试运行失败,并返回以下信息: + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +我们无法从失败信息中获得有用的东西,只能说:“好吧,原本预期为真的表达式,现在却为假。但这是为什么呢?” +像这样的困惑会降低我们的效率,因为我们现在不得不花时间理解这些测试代码。 + +## 更好的失败返回信息,第一部分:手动设定 `XCTAssert` 的返回信息 + +`XCTAssert` 这个断言(Assertion)允许我们设定运行失败时的返回信息(下面简称“返回信息”),这当然有一定的作用: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +但是,我们就不得不亲自设置这些返回信息。 + +## 更好的失败返回信息,第二部分:Nimble 的返回信息 + +Nimble 能让你的测试断言及其返回信息更便于阅读: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +我们不需要再亲自设置返回信息,因为 Nimble 提供的信息已经非常清楚了: + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: VerySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +这个返回信息清楚地点明了出错的地方:预期中 `kiki` 应该包含在 `silliest()` 的返回值里面,但是实际的返回值只包含 `jane` 。现在我们知道问题出在哪了,因此很容易解决问题: + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble 提供了很多种类的断言,每个断言都带有清晰的返回信息。与 `XCTAssert` 不同,你不需要每次都亲自设定返回信息。 + +完整的 Nimble 断言列表,请参考 [Nimble README](https://github.com/Quick/Nimble) 。 +下面是一些例子,先睹为快: + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md new file mode 100644 index 0000000..255c278 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md @@ -0,0 +1,461 @@ +# 用 Quick 例子和例子群组织测试 + +Quick 使用特殊的语法定义**例子(examples)**和**例子群(example groups)**。 + +在*[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)*,我们了解了一个好的测试方法名称是至关重要的,尤其是当测试失败时。它能够帮助我们判断是修改程序代码或者是更新测试内容。 + +Quick 的例子和例子群主要有两个目的: + +1. 它们促使你使用具有描述性的测试名称。 +2. 它们极大地简化了 Arrange 步骤的测试代码。 + +## 例子:使用 `it` + +定义了 `it` 函数的例子,使用断言代码指明了程序应有的行为。这些就像 XCTest 中的测试方法一样。 + +`it` 函数有两个参数:例子的名称和闭包。下面这个例子具体说明了 `Sea.Dolphin` 类应有的行为。 +一只新的海豚(dolphin)应该是聪明(smart)且友好(friendly)的: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +用描述性的语言使例子所测试的内容清晰明了。 +描述性的语言可以是任意长度、任意字符的,涵盖了英语以及其他语言的字符,甚至可以是表情符号!:v: :sunglasses: + +## 例子群:使用 `describe` 和 `context` + +例子群是按一定逻辑关系组织的例子。例子群里可以共享配置(setup)和卸载(teardown)代码。 + +### 使用 `describe` 描述类和方法 + +为了具体说明 `Dolphin` 类中 `click` 方法的行为 —— 换句话说,为了验证这个方法可用 —— 我们可以把多个 `it` 例子用 `describe` 函数组织成为一个群。把相同的例子组织在一起能更方便阅读: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +当这两个例子在 Xcode 中运行的时候,它们会从 `describe` 和 `it` 函数中输出一些描述性的语言: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +显然,这两个测试各自测试的内容都很清晰明了。 + +### 使用 `beforeEach` 和 `afterEach` 共享配置/卸载代码 + +例子群不仅使它包含的例子更清晰易懂,还有助于在群里共享配置和卸载的代码。 + +在下面的这个示例里,例子群中的每一个例子前面,都用 `beforeEach` 这个函数创建一种新类型的海豚以及它特定的叫声。 +这就保证了对每个例子进行了初始化: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +对于海豚这个例子来说,像这样共享配置代码并不是一个很大的工程。但是对于更复杂的对象,共享代码能够省去大量写代码的时间! + +如果想在每个例子后面执行特定的代码,可以使用 `afterEach`。 + +### 使用 `context` 指定条件的行为 + +海豚使用叫声进行回声定位。当接近了它们感兴趣的东西时,海豚会发出一系列的超声波对其进行更准确的探测。 + +这个测试需要展示在不同环境下,`click` 方法的不同行为。通常,海豚只叫(click)一声。但是当海豚接近它们感兴趣的东西时,它会发出很多次叫声。 + +这种情况可以用 `context` 函数来表示:一个 `context` 代表正常情况,另一个 `context` 代表海豚接近感兴趣的东西: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +严格地说,`context` 是 `describe` 的一种同义的表达,但是像这样有目的地使用能够让你的代码更容易理解。 + +### 测试的可读性:Quick 和 XCTest + +在*[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)*里,我们知道了对每种情况进行一个测试能够很方便地组织测试代码。 +在 XCTest 里,这样做会导致出现冗长的测试方法名称: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +使用 Quick ,每种情况会更容易阅读,并且我们能够为每一个例子群进行配置: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 临时禁用例子或例子群 + +你可以临时禁用那些测试不通过的例子和例子群。 +这些例子的名称会随着测试结果一起打印在控制台里,但它们并不运行。 + +通过添加前缀 `x` 就能禁用例子或例子群: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 临时运行一部分例子 + +在某些情况下,只关注一个或几个例子有助于测试。毕竟只运行一两个例子比运行整个测试快多了。通过使用 `fit` 函数,你可以只运行一两个例子。你还可以使用 `fdescribe` 或 `fcontext` 把测试重点放在一个例子群: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## 使用 `beforeSuite` 和 `afterSuite` 进行全局配置/卸载 + +有一些测试的配置需要在所有例子运行之前进行。对于这种情况,可以使用 `beforeSuite` 和 `afterSuite` 。 + +下面的示例展示了在所有其他例子运行之前,创建一个包含了海洋中所有生物的数据库。当所有例子运行结束的时候,这个数据库就被卸载: + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +你可以添加多个 `beforeSuite` 和 `afterSuite` 。所有的 +`beforeSuite` 闭包都会在其它测试运行前执行,同样,所有的 +`afterSuite` 闭包都会在其它测试运行结束后执行。 +但是这些闭包并不一定按先后顺序执行。 + +## 访问当前例子的元数据 + +在某些情况下,你会想知道当前运行的例子的名称,或者目前已经运行了多少例子。Quick 提供了闭包 `beforeEach` 和 `afterEach` ,通过这些闭包,可以访问元数据。 + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md new file mode 100644 index 0000000..22318a0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md @@ -0,0 +1,52 @@ +# 在 Objective-C 中使用 Quick + +Quick 既支持 Swift ,也支持 Objective-C 。 + +但是,在 Objective-C 下使用 Quick 时,有以下两点需要注意。 + +## 可选的速记语法 + +在 Objective-C 文件中导入的 Quick 框架,包含了名为 `it` 和 +`itShouldBehaveLike` 的宏,还包含了名为 `context()` 和 `describe()` 的函数。 + +如果你在测试项目的时候,也定义了同名的量或者函数,那么就会出现错误。因此,这种情况下,你可以通过禁用 Quick 的可选速记语法来避免命名冲突: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +注意,必须在 `@import Quick;` 之前,定义宏:`QUICK_DISABLE_SHORT_SYNTAX` 。 + +当然,你也可以选择在测试目标(target)的设置里面定义宏: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## 你的测试目标必需至少包含一个 Swift 文件 + +如果你的测试目标没有*至少包含一个 Swift 文件*,那么 Swift 标准库就不会链接到你的测试目标,因而会导致 Quick 无法正常编译。 + +当没有至少包含一个 Swift 文件时,测试运行后就会终止并且返回以下错误: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +只需要在测试目标下添加一个空的 Swift 文件,如 `SwiftSpec.swift` 就可以解决这个问题: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> 更多关于这个问题的细节,请参考 https://github.com/Quick/Quick/issues/164 。 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md new file mode 100644 index 0000000..2c48f4c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md @@ -0,0 +1,18 @@ +# 文档 + +Quick 能够帮助你验证你的 Swift 和 Objective-C 程序的行为。然而,能提高你的测试技巧的不仅仅是了解如何使用 Quick。下面这些指南能够帮助你更有效地写测试 —— 不仅是和 Quick 相关的,更包括 XCTest 还有其他的测试框架。 + +每份指南都有一个主题。如果你对单元测试完全陌生,建议你按照从上往下的顺序阅读。 + +- **[在项目中添加测试](SettingUpYourXcodeProject.md)**:如果你遇到在项目中构建测试的问题,请阅读这份指南。 +- **[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)**:阅读这份指南来了解如何更高效快速地编写 `XCTestCase` 测试。 +- **[不要测试代码,而应该测试行为](BehavioralTesting.md)**:通过这份指南你能学习到哪些是好的测试,哪些是不好的测试。 +- **[测试 OS X 和 iOS 应用](TestingApps.md)**:了解如何为使用 AppKit 和 UIKit 框架的代码编写测试。 +- **[使用测试替身进行测试](TestUsingTestDoubles.md)**:阅读这份指南来了解什么是测试替身,以及如何使用它们。 +- **[使用 Shared Assertion 来复用测试模板代码](SharedExamples.md)**:学习如何在测试中共享测试代码。 +- **[配置 Quick 的行为](ConfiguringQuick.md)**:阅读这份指南来了解如何在运行测试代码时改变 Quick 的行为。 +- **[在 Objective-C 中使用 Quick](QuickInObjectiveC.md)**:如果你在 Objective-C 项目使用 Quick 的过程中遇到了困难,请阅读这份指南。 +- **[安装 Quick](InstallingQuick.md)**:通过这份指南了解在项目中添加 Quick 的方法:Git submodules,CocoaPods,Carthage 和 Swift Package Manager 。 +- **[安装 Quick 文件模板](InstallingFileTemplates.md)**:阅读这份指南来了解如何安装文件模板以提高编写 Quick specs 的效率。 +- **[更多资料](MoreResources.md)**:更多关于 OS X 和 iOS 测试的资源。 +- **[常见的问题](Troubleshooting.md)**:当你遇到问题的时候,请阅读这份指南。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..e902c6f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md @@ -0,0 +1,75 @@ +# 在项目中添加测试 + +除了命令行项目以外,当你在 Xcode 7 中创建新项目时,单元测试 Target 默认是包含的。[为命令行项目设置测试 Target](#setting-up-a-test-target-for-a-command-line-tool-project) 要编写单元测试,你需要能够在测试 Target 中使用主 target 代码。 + +## 用 Swift 测试 Swift 项目代码 + +为了测试用 Swift 写的代码,你需要做以下两件事: + +1. 将 `.xcodeproj` 中的 "defines module" 设置为 `YES`。 + + * Xcode 中具体操作方法:选中你的项目,选择 "Build Settings" 选项列表,选中 "Defines Modules" 行,修改其值为 "Yes"。 + +2. 在单元测试中添加 `@testable import YourAppModuleName`。这会把所有 `public` 和 `internal` (默认访问修饰符) 修饰符暴露给测试代码。但 `private` 修饰符仍旧保持私有。 + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> 一些开发者提倡添加 Swift 源文件至测试 target。然而这会导致以下问题 [subtle, hard-to-diagnose errors](https://github.com/Quick/Quick/issues/91),所以并不推荐。 + +## 使用 Swift 测试 Objective-C 项目代码 + +1. 给你的测试 target 添加 bridging header 文件。 +2. 在 bridging header 文件中,引入待测试的代码文件。 + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +现在就可以在 Swift 测试文件中使用 `MyClass.h` 中的代码了。 + +## 使用 Objective-C 测试 Swift 项目代码 + +1. 使用 `@objc` 桥接需要使用 Objective-C 测试的 Swift 类和方法。 +2. 在单元测试中引入模块的 Swift 头文件。 + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## 使用 Objective-C 测试 Objective-C 项目代码 + +在测试 target 中引入待测试的代码文件: + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### 为命令行项目设置测试 Target + +1. 在项目窗格中添加一个项目target。 +2. 选择 "OS X Unit Testing Bundle"。 +3. 编辑主target的 scheme。 +4. 选中 "Test" 条目,单击 "Info" 下的 "+",选择需要测试的 bundle。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md new file mode 100644 index 0000000..ec87138 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md @@ -0,0 +1,113 @@ +# 使用 Shared Assertion 来复用测试模板代码 + +在某种场合下,一些特定的测试代码可以应用在不同的对象上。 + +比如,假设有一个叫 `Edible` 的协议。当一只海豚吃了标识为 `Edible` 的食物时,它会变得高兴。`Mackerel` 和 `Cod` 都遵循 `Edible` 协议。这个时候,Quick 的 shared example(共享用例)能帮你更容易地测试 `Mackerel` 和 `Cod` 的行为。 + +下面的例子为一些 `Edible` 的食物定义了一组共享用例,以测试 mackerel 和 cod 的行为。 + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +共享用例可以包括任意数量的 `it`, `context` 和 `describe` 代码块。当使用它们来测试不同对象的相同行为时,你可以少写*很多*不必要的重复代码。 + +一般来说,你使用共享用例进行测试时不需要依赖其他额外的对象。在 Swift 中,你可以简单地用一个不带参数的 `sharedExample` 闭包来使用共享用例。当你需要进行全局测试时,这很有用。 + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` +> 如果你使用 Objective-C 的话,你需要传入一个带 `QCKDSLSharedExampleContext` 参数的 block,即使你并不打算使用它。不好意思,你只能这样做,人生有时就是这么的无奈。:cookie: :bomb: + +你也可以使用 `fitBehavesLike` 函数来单独测试共享用例。 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md new file mode 100644 index 0000000..9e83ead --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md @@ -0,0 +1,131 @@ +# 使用模拟对象进行测试 + +## 测试替身 + +下面的问题在写测试时经常出现。比如:`Car` 依赖于/使用 `Tire` 。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests` 用来测试调用了 `Tire` 的 `Car` 。这时候,在 `Tire` 里出现的 bug 会导致 `CarTests` 测试失败(即使 `Car` 是没有错误的)。 + +这时候很难说清楚到底是什么出错了。为了避免这个问题,我们可以使用一个替身对象,来代替 `CarTests` 里面的 `Tire` 。对于这个问题,我们会为 `Tire` 创建一个替身对象,命名为 `PerfectTire` 。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` 具有和 `Tire` 一样的函数和属性。但是,这些函数和属性的实现可能会有所不同。 + +像 `PerfectTire` 这样的对象叫做“测试替身”。测试替身充当替身对象,用于独立测试多个相关对象的功能。以下是测试替身的几种类型: + +- 模拟对象:用于从测试类中接收输出。 +- 桩对象:用于为测试类提供输入。 +- 伪对象:具有与原来的类相似的行为。 + +我们先了解一下如何使用模拟对象。 + +## 模拟对象 + +模拟对象着眼于说明它与其它对象的正确交互,并且当出现错误时用来检测问题。模拟对象应该事先知道测试时会发生什么,并且该做出怎样的反应。 + +### 在 Swift 中使用模拟对象来写测试 + +#### 应用案例 + +例如,我们有一个应用,它会从互联网上获取数据。 + +* 在 `ViewController` 中展示从互联网上获取的数据。 +* 自定义类,实现 `DataProviderProtocol` ,负责获取数据。 + +`DataProviderProtocol` 如下定义: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` 从互联网上获取数据,并通过闭包 `callback` 返回数据。 + +下面的 `DataProvider` 实现了 `DataProviderProtocol` 协议。 + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = NSURL(string: "http://example.com/")! + let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) + let task = session.dataTaskWithURL(url, completionHandler: { + (data, resp, err) in + let string = NSString(data:data!, encoding:NSUTF8StringEncoding) as! String + callback(data: string) + }) + task.resume() + } +} +``` + +在我们这个场景里,`ViewController` 的 `viewDidLoad()` 里调用了 `fetch()` 。 + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### 用 `DataProviderProtocol` 协议的模拟对象进行测试 + +`ViewController` 依赖于 `DataProviderProtocol` 协议。为了测试这个 viewController ,要创建一个遵循 `DataProviderProtocol` 的模拟对象。 + +模拟对象是非常有用的。因为使用它,你可以: + +- 更快地运行测试。 +- 即使未联网也可以进行测试。 +- 对 `ViewController` 进行独立测试。 + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +当 `fetch()` 被调用的时候,`fetchCalled` 会被设为 `true` 。这样能使测试代码确认对象是否准备好进行测试。 + +下面的代码验证了当 `ViewController` 加载时,会运行 `dataProvider.fetch()` 。 + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvier = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvier = mockProvier + + expect(mockProvier.fetchCalled).to(equal(false)) + + let _ = viewController.view + + expect(mockProvier.fetchCalled).to(equal(true)) + } + } +} +``` + +如果你对写测试感兴趣,想学习更多的内容,请参考 https://realm.io/news/testing-in-swift/ 。 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md new file mode 100644 index 0000000..59f68d8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md @@ -0,0 +1,174 @@ +# 测试 OS X 和 iOS 应用 + +*[在项目中添加测试](SettingUpYourXcodeProject.md)* 这篇文章详细介绍了有关如何测试 Objective-C 和 Swift 的函数和类的内容。 +本文将介绍一些额外的技巧,用来测试**类**,如 `UIViewController` 及其子类。 + +> 你可以参考这个简短的 [Lightning Talk](https://vimeo.com/115671189#t=37m50s)(从37分50秒开始),它涵盖了绝大多数这方面的话题。 + +## 触发 `UIViewController` 生命周期事件 + +通常,当你的视图控制器(view controller)呈现在应用中,UIKit 会自动触发生命周期事件。然而,在测试 `UIViewController` 的时候,你需要自己手动触发这些事件。你可以通过以下任意一种方法来实现它: + +1. 通过访问 `UIViewController.view` 来触发事件,如: `UIViewController.viewDidLoad()` 。 +2. 使用 `UIViewController.beginAppearanceTransition()` 来触发大多数生命周期事件。 +3. 直接调用方法,如:`UIViewController.viewDidLoad()` 或 `UIViewController.viewWillAppear()` 。 + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## 初始化在故事板(Storyboard)中定义的视图控制器 + +为了初始化在故事板中定义的视图控制器,你需要先为它分配一个 **Storyboard ID** : + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +为视图控制器分配 ID 后,就可以在测试中初始化了: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## 触发 UIControl 事件(如:点击按钮) + +按钮以及其他继承自 `UIControl` 的 UIKit 类定义了一些方法,使我们能够通过程序代码发送控制事件,如:点击按钮。 +以下代码演示了如何测试点击按钮触发的行为: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md new file mode 100644 index 0000000..c89e25e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md @@ -0,0 +1,10 @@ +# 常见的安装问题 + +这里有一些解决方案,用来处理使用框架时遇到的一些问题。 + +## No such module 'Quick' + +- 如果你已经运行了 `pod install` ,那么关闭并重新打开 Xcode workspace 。如果这样做还没解决问题,那么请接着进行下面的步骤。 +- 删除 `~/Library/Developer/Xcode/DerivedData` **整个**目录,这里面包含了 `ModuleCache` 。 +- 在 Manage Schemes 对话框中,勾选 `Quick` 、`Nimble` 、`Pods-ProjectnameTests` ,然后重新编译它们(`Cmd+B`)。 + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Nimble/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore new file mode 100644 index 0000000..6930efd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore @@ -0,0 +1,29 @@ +.DS_Store +**/xcuserdata/* +**/*.xccheckout +**/*.xcscmblueprint +build/ +.idea +DerivedData/ +Nimble.framework.zip + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts +Carthage/Checkouts/**/*.* +Carthage/Checkouts/**/Cart* +Carthage/Checkouts/**/Tests +!Carthage/Checkouts/**/LICENSE.* +!Carthage/Checkouts/**/*.md +!Carthage/Checkouts/**/*.swift +!Carthage/Checkouts/**/*.h +!Carthage/Checkouts/**/*.m +!Carthage/Checkouts/**/*.c +Carthage/Build + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml new file mode 100644 index 0000000..cb105e7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml @@ -0,0 +1,19 @@ +disabled_rules: + - todo + - variable_name + - force_try + - force_cast + +included: + - Sources + - Tests + +excluded: + - Carthage/Checkouts + +trailing_comma: + mandatory_comma: true + +line_length: + ignores_comments: true + ignores_function_declarations: true diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml new file mode 100644 index 0000000..20d7f7d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml @@ -0,0 +1,39 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + sudo: required + env: TYPE=podspec + - os: osx + env: TYPE=ios NIMBLE_RUNTIME_IOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=tvos NIMBLE_RUNTIME_TVOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=macos + - os: osx + env: TYPE=macos + osx_image: xcode9 + - os: osx + env: TYPE=swiftpm + - os: osx + env: TYPE=swiftpm + osx_image: xcode9 + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + - os: linux + dist: trusty + sudo: required + env: + - TYPE=swiftpm + - SWIFT_VERSION=4.0.2 + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" +install: + - if [[ "$TYPE" == "podspec" ]]; then sudo gem install bundler; bundle install; fi +script: + - ./test $TYPE diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md @@ -0,0 +1,120 @@ + + + +- [Welcome to Nimble!](#welcome-to-nimble!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + + + +# Welcome to Nimble! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Nimble should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +**tl;dr:** If you've added a file to the project, make sure it's +included in both the OS X and iOS targets. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Nimble (eg - v2.0.0 or git sha `20a3f3b4e63cc8d97c92c4164bf36f2a2c9a6e1b`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- Use `Nimble.xcodeproj` to work on Nimble. + +## Running the Swift Package Manager tests + +1. Install `swiftenv` by running a line from the build script (`.travis.yml`): + + eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" + +2. Run `./test swiftpm` + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of Nimble + before submitting your pull request. You can run all the OS X & iOS unit + tests using `./test`. +- If you've added a file to the project, make sure it's included in both + the OS X and iOS targets. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +### Code of Conduct + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +### Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Nimble/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Update [Quick](https://github.com/Quick/Quick) + - Update Quick's submodule reference to the newly released Nimble version + - Update Nimble version in `README.md` and Documentation in [Quick](https://github.com/Quick/Quick) if it's not a patch version update. +- Announce! diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private new file mode 100644 index 0000000..8e95dd6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private @@ -0,0 +1 @@ +github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved new file mode 100644 index 0000000..3984e09 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved @@ -0,0 +1,2 @@ +github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923" +github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt new file mode 100644 index 0000000..ca8f5b8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift new file mode 100644 index 0000000..c1e2ed8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift @@ -0,0 +1,9 @@ +import PackageDescription + +let package = Package( + name: "CwlCatchException", + targets: [ + Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]), + Target(name: "CwlCatchExceptionSupport") + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md new file mode 100644 index 0000000..0f97b03 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md @@ -0,0 +1,46 @@ +# 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. + +## 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), + +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" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..3e89e23 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,35 @@ +// +// CwlCatchException.swift +// CwlAssertionTesting +// +// 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 + +#if SWIFT_PACKAGE +import CwlCatchExceptionSupport +#endif + +private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { + return catchExceptionOfKind(type, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + return catchReturnTypeConverter(self, block: block) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m new file mode 100644 index 0000000..8cf414f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m @@ -0,0 +1,37 @@ +// +// CwlCatchException.m +// CwlAssertionTesting +// +// 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 "CwlCatchException.h" + +#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +__attribute__((visibility("hidden"))) +#endif +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h new file mode 100644 index 0000000..0c8dd87 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h @@ -0,0 +1,32 @@ +// +// CwlCatchException.h +// CwlCatchException +// +// 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 + +//! 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)); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt new file mode 100644 index 0000000..693a2fe --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift new file mode 100644 index 0000000..8792aac --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift @@ -0,0 +1,19 @@ +import PackageDescription + +let package = Package( + name: "CwlPreconditionTesting", + targets: [ + Target(name: "CwlPreconditionTesting", dependencies: [ + "CwlMachBadInstructionHandler" + ]), + Target(name: "CwlMachBadInstructionHandler") + ], + dependencies: [ + .Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])), + ], + exclude: [ + "Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a42a5b5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md @@ -0,0 +1,73 @@ +# CwlPreconditionTesting + +A Mach exception handler, written in Swift and Objective-C, that allows `EXC_BAD_INSTRUCTION` (as raised by Swift's `assertionFailure`/`preconditionFailure`/`fatalError`) to be caught and tested. + +NOTE: the iOS code runs in the simulator *only*. It is for logic testing and cannot be deployed to the device due to the Mach exception API being private on iOS. + +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) + +## 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), + +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/CwlPreconditionTesting.git", majorVersion: 1) + +### CocoaPods + +Add the following lines to your target in your "Podfile": + + pod 'CwlPreconditionTesting', :git => 'https://github.com/mattgallagher/CwlPreconditionTesting.git' + pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git' + +### Carthage + +Add the following line to your Cartfile: + + git "https://github.com/mattgallagher/CwlPreconditionTesting.git" "master" + +## 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) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m new file mode 100644 index 0000000..8183196 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m @@ -0,0 +1,50 @@ +// +// CwlMachBadExceptionHandler.m +// 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. +// + +#if defined(__x86_64__) + + #import "mach_excServer.h" + #import "CwlMachBadInstructionHandler.h" + + @protocol BadInstructionReply + +(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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h new file mode 100644 index 0000000..aef59c2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -0,0 +1,70 @@ +// +// CwlMachBadInstructionHandler.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 +#import + +NS_ASSUME_NONNULL_BEGIN + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; +} request_mach_exception_raise_t; + +// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; +} reply_mach_exception_raise_state_t; + +typedef struct +{ + mach_port_t exception_port; + exception_type_t exception; + mach_exception_data_type_t const * _Nullable code; + mach_msg_type_number_t codeCnt; + int32_t * _Nullable flavor; + natural_t const * _Nullable old_state; + mach_msg_type_number_t old_stateCnt; + thread_state_t _Nullable new_state; + mach_msg_type_number_t * _Nullable new_stateCnt; +} bad_instruction_exception_reply_t; + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c new file mode 100644 index 0000000..733c564 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Sun Jan 29 19:05:29 2017 + * with a MiG generated by bootstrap_cmds-96.20.2 + * OPTIONS: + */ + +#if defined(__x86_64__) + +/* Module mach_exc */ + +#define __MIG_check__Request__mach_exc_subsystem__ 1 + +#include "mach_excServer.h" + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + + typedef __Request__mach_exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise") + __BeforeRcvRpc(2405, "mach_exception_raise") + +#if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state") + __BeforeRcvRpc(2406, "mach_exception_raise_state") + +#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") + +#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity") +} + + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = { + mach_exc_server_routine, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + OutHeadP->msgh_reserved = 0; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h new file mode 100644 index 0000000..52e53ae --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h @@ -0,0 +1,321 @@ +#ifndef _mach_exc_server_ +#define _mach_exc_server_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +/* BEGIN MIG_STRNCPY_ZEROFILL CODE */ + +#if defined(__has_include) +#if __has_include() +#ifndef USING_MIG_STRNCPY_ZEROFILL +#define USING_MIG_STRNCPY_ZEROFILL +#endif +#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ +#endif /* __has_include() */ +#endif /* __has_include */ + +/* END MIG_STRNCPY_ZEROFILL CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigServerHeader +__BeforeMigServerHeader +#endif /* __BeforeMigServerHeader */ + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +mig_routine_t mach_exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +extern const struct catch_mach_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem; + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + + +/* union of all requests */ + +#ifndef __RequestUnion__catch_mach_exc_subsystem__defined +#define __RequestUnion__catch_mach_exc_subsystem__defined +union __RequestUnion__catch_mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2405 },\ + { "mach_exception_raise_state", 2406 },\ + { "mach_exception_raise_state_identity", 2407 } +#endif + +#ifdef __AfterMigServerHeader +__AfterMigServerHeader +#endif /* __AfterMigServerHeader */ + +#endif /* _mach_exc_server_ */ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..91e5d4d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,89 @@ +// +// CwlBadInstructionException.swift +// 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 + +#if SWIFT_PACKAGE + import CwlMachBadInstructionHandler +#endif + +private func raiseBadInstructionException() { + BadInstructionException().raise() +} + +/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type. +@objc(BadInstructionException) +public class BadInstructionException: NSException { + static var name: String = "com.cocoawithlove.BadInstruction" + + init() { + super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// 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 = 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 = 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.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 + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..f96ec63 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,197 @@ +// +// CwlCatchBadInstruction.swift +// 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 + +#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) + } + } + + extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> 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(in block: (UnsafeMutablePointer) -> 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() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil + + static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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.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.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 + } + + /// 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) + } + } + + 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 + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift new file mode 100644 index 0000000..eb9bc19 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift @@ -0,0 +1,108 @@ +// +// 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.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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..8d99d5e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,55 @@ +// +// CwlDarwinDefinitions.swift +// 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 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.size / MemoryLayout.size) + + public let EXC_TYPES_COUNT = 14 + public struct execTypesCountTuple { + // 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 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h new file mode 100644 index 0000000..f9dbedd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h @@ -0,0 +1,30 @@ +// +// 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 + +//! 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" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h new file mode 100644 index 0000000..3434a71 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h @@ -0,0 +1,27 @@ +// +// 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 + +//! Project version number for CwlUtils. +FOUNDATION_EXPORT double CwlPreconditionTesting_POSIXVersionNumber; + +//! Project version string for CwlUtils. +FOUNDATION_EXPORT const unsigned char CwlAssertingTesting_POSIXVersionString[]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test new file mode 100644 index 0000000..a995ae2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test @@ -0,0 +1,3 @@ +FROM swift:latest +COPY . . +CMD ./test swiftpm diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile new file mode 100644 index 0000000..eca9219 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.5.0' diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock new file mode 100644 index 0000000..36a0839 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock @@ -0,0 +1,76 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + atomos (0.1.2) + claide (1.0.2) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + minitest (5.11.3) + molinillo (0.6.5) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + ruby-macho (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.5.0) + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec new file mode 100644 index 0000000..f3fed7e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec @@ -0,0 +1,53 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "7.1.1" + 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. + DESC + 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.osx.deployment_target = "10.10" + s.tvos.deployment_target = "9.0" + s.source = { :git => "https://github.com/Quick/Nimble.git", + :tag => "v#{s.version}" } + + s.source_files = [ + "Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlCatchException/Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/**/*.{swift,h,m,c}", + ] + + s.osx.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.ios.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.tvos.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", + ] + + s.private_header_files = "Sources/NimbleObjectiveC/CurrentTestCaseTracker.h" + + s.exclude_files = "Sources/Nimble/Adapters/NonObjectiveC/*.swift" + s.weak_framework = "XCTest" + s.requires_arc = true + s.compiler_flags = '-DPRODUCT_NAME=Nimble/Nimble' + s.pod_target_xcconfig = { + 'ENABLE_BITCODE' => 'NO', + 'OTHER_LDFLAGS' => '-weak-lswiftXCTest', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..91ec261 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2353 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + A8F2B2541E79A4AB005BDD17 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + A8F2B2581E79A4B0005BDD17 /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F1A74291940169200FFFC47 /* Nimble.framework */; }; + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 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 */; }; + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A56671A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; }; + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; }; + 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 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; }; + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; }; + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; }; + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + 1F5DF1AA1BDCA10200C3A531 /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F925EAD195C0D6300ED456B /* Nimble.framework */; }; + 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F925EE2195C0DFD00ED456B /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFD195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 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 */; }; + 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 */; }; + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C41E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.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 */; }; + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + CD79C9A51D2CC848004B6F9A /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + CD79C9A71D2CC848004B6F9A /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + CD79C9AF1D2CC848004B6F9A /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; }; + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 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 */; }; + 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 */; }; + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; }; + 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, ); }; }; + CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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 */; }; + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F5DF1541BDCA0CE00C3A531; + remoteInfo = "Nimble-tvOS"; + }; + 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = ""; }; + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTests.swift; sourceTree = ""; }; + 1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = ""; }; + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSL.h; sourceTree = ""; }; + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSL.m; sourceTree = ""; }; + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBExceptionCapture.h; sourceTree = ""; }; + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBExceptionCapture.m; sourceTree = ""; }; + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBStringify.h; sourceTree = ""; }; + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBStringify.m; sourceTree = ""; }; + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBExpectation.swift; sourceTree = ""; }; + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBObjCMatcher.swift; sourceTree = ""; }; + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionCapture.swift; sourceTree = ""; }; + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMatcherWrapper.swift; sourceTree = ""; }; + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherFunc.swift; sourceTree = ""; }; + 1F1A74291940169200FFFC47 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A742D1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1A742E1940169200FFFC47 /* Nimble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nimble.h; sourceTree = ""; }; + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A743A1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAKindOfTest.swift; sourceTree = ""; }; + 1F2752D119445B8400052A26 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = README.md; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.markdown; }; + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmptyTest.swift; sourceTree = ""; }; + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAsyncTest.m; sourceTree = ""; }; + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NimbleSpecHelper.h; sourceTree = ""; }; + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeAnInstanceOfTest.m; sourceTree = ""; }; + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeKindOfTest.m; sourceTree = ""; }; + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeCloseToTest.m; sourceTree = ""; }; + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeginWithTest.m; sourceTree = ""; }; + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanTest.m; sourceTree = ""; }; + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeIdenticalToTest.m; sourceTree = ""; }; + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanTest.m; sourceTree = ""; }; + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTruthyTest.m; sourceTree = ""; }; + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalsyTest.m; sourceTree = ""; }; + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTrueTest.m; sourceTree = ""; }; + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalseTest.m; sourceTree = ""; }; + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeNilTest.m; sourceTree = ""; }; + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainTest.m; sourceTree = ""; }; + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEndWithTest.m; sourceTree = ""; }; + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEqualTest.m; sourceTree = ""; }; + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCMatchTest.m; sourceTree = ""; }; + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCRaiseExceptionTest.m; sourceTree = ""; }; + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertionTest.swift; sourceTree = ""; }; + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSyncTest.m; sourceTree = ""; }; + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoidTest.swift; sourceTree = ""; }; + 1F91DD301C74BF61002C309F /* BeVoid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoid.swift; sourceTree = ""; }; + 1F925EAD195C0D6300ED456B /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousTest.swift; sourceTree = ""; }; + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOfTest.swift; sourceTree = ""; }; + 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaisesExceptionTest.swift; sourceTree = ""; }; + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLogicalTest.swift; sourceTree = ""; }; + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseToTest.swift; sourceTree = ""; }; + 1F925EF8195C175000ED456B /* BeNilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeNilTest.swift; sourceTree = ""; }; + 1F925EFB195C186800ED456B /* BeginWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeginWithTest.swift; sourceTree = ""; }; + 1F925EFE195C187600ED456B /* EndWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWithTest.swift; sourceTree = ""; }; + 1F925F01195C189500ED456B /* ContainTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainTest.swift; sourceTree = ""; }; + 1F925F04195C18B700ED456B /* EqualTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EqualTest.swift; sourceTree = ""; }; + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanTest.swift; sourceTree = ""; }; + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanTest.swift; sourceTree = ""; }; + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanOrEqualToTest.swift; sourceTree = ""; }; + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanOrEqualToTest.swift; sourceTree = ""; }; + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeEmptyTest.m; sourceTree = ""; }; + 1FA0C3FE1E30B14500623165 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToTest.swift; sourceTree = ""; }; + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleEnvironment.swift; sourceTree = ""; }; + 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotificationTest.swift; sourceTree = ""; }; + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotification.swift; sourceTree = ""; }; + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionRecorder.swift; sourceTree = ""; }; + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdapterProtocols.swift; sourceTree = ""; }; + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleXCTestHandler.swift; sourceTree = ""; }; + 1FD8CD081968AB07008ED995 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + 1FD8CD091968AB07008ED995 /* Expectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expectation.swift; sourceTree = ""; }; + 1FD8CD0A1968AB07008ED995 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailureMessage.swift; sourceTree = ""; }; + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOf.swift; sourceTree = ""; }; + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeAKindOf.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseTo.swift; sourceTree = ""; }; + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmpty.swift; sourceTree = ""; }; + 1FD8CD111968AB07008ED995 /* BeginWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeginWith.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThanOrEqualTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeIdenticalTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThanOrEqual.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD171968AB07008ED995 /* BeLogical.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLogical.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD181968AB07008ED995 /* BeNil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeNil.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1A1968AB07008ED995 /* Contain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Contain.swift; sourceTree = ""; }; + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWith.swift; sourceTree = ""; }; + 1FD8CD1C1968AB07008ED995 /* Equal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Equal.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = ""; }; + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = ""; }; + 1FD8CD261968AB07008ED995 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = ""; }; + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = ""; }; + 1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = ""; }; + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionDispatcher.swift; sourceTree = ""; }; + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpectationMessage.swift; sourceTree = ""; }; + 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowErrorTest.swift; sourceTree = ""; }; + 29EA59651B551EE6002D767E /* ThrowError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowError.swift; sourceTree = ""; }; + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseProvider.swift; sourceTree = ""; }; + 472FD1341B9E085700C7B8DA /* HaveCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCount.swift; sourceTree = ""; }; + 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCountTest.swift; sourceTree = ""; }; + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCountTest.m; sourceTree = ""; }; + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = ""; }; + 7A0A26221E7F52360092A34E /* ToSucceed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceed.swift; sourceTree = ""; }; + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceedTest.swift; sourceTree = ""; }; + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfying.swift; sourceTree = ""; }; + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfyingTest.m; sourceTree = ""; }; + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfyingTest.swift; sourceTree = ""; }; + 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOfTest.swift; sourceTree = ""; }; + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOf.swift; sourceTree = ""; }; + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAnyOfTest.m; sourceTree = ""; }; + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcStringersTest.m; sourceTree = ""; }; + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertion.swift; sourceTree = ""; }; + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCUserDescriptionTest.m; sourceTree = ""; }; + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDescriptionTest.swift; sourceTree = ""; }; + A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAllOfTest.swift; sourceTree = ""; }; + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAllOfTest.m; sourceTree = ""; }; + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatisfyAllOf.swift; sourceTree = ""; }; + AE4BA9AC1C88DDB500B73906 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchError.swift; sourceTree = ""; }; + AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = ""; }; + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = ""; }; + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = ""; }; + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = ""; }; + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = ""; }; + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_excServer.h; sourceTree = ""; }; + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DSL+Wait.swift"; sourceTree = ""; }; + DD72EC631A93874A002F7651 /* AllPassTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPassTest.swift; sourceTree = ""; }; + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToObjectTest.swift; sourceTree = ""; }; + DDB1BC781A92235600F743C3 /* AllPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPass.swift; sourceTree = ""; }; + DDB4D5EC19FE43C200E9D9FE /* Match.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Match.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchTest.swift; sourceTree = ""; }; + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAllPassTest.m; sourceTree = ""; }; + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+Register.m"; sourceTree = ""; }; + F8A1BE321CB3777F00031679 /* CurrentTestCaseTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CurrentTestCaseTracker.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F1A74251940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74311940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA9195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB4195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F14FB61194180A7009F2A08 /* Helpers */ = { + isa = PBXGroup; + children = ( + 1F14FB63194180C5009F2A08 /* utils.swift */, + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */, + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */ = { + isa = PBXGroup; + children = ( + F8A1BE321CB3777F00031679 /* CurrentTestCaseTracker.h */, + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */, + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */, + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */, + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */, + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */, + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */, + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */, + ); + name = NimbleObjectiveC; + path = Sources/NimbleObjectiveC; + sourceTree = ""; + }; + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */, + ); + path = NonObjectiveC; + sourceTree = ""; + }; + 1F1A741F1940169200FFFC47 = { + isa = PBXGroup; + children = ( + 1F2752D119445B8400052A26 /* README.md */, + 1F1A742B1940169200FFFC47 /* Nimble */, + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */, + 1F1A74381940169200FFFC47 /* NimbleTests */, + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */, + 1F1A742A1940169200FFFC47 /* Products */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + usesTabs = 0; + }; + 1F1A742A1940169200FFFC47 /* Products */ = { + isa = PBXGroup; + children = ( + 1F1A74291940169200FFFC47 /* Nimble.framework */, + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */, + 1F925EAD195C0D6300ED456B /* Nimble.framework */, + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */, + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */, + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 1F1A742B1940169200FFFC47 /* Nimble */ = { + isa = PBXGroup; + children = ( + 1FD8CD041968AB07008ED995 /* Adapters */, + 1FD8CD081968AB07008ED995 /* DSL.swift */, + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */, + 1FD8CD091968AB07008ED995 /* Expectation.swift */, + 1FD8CD0A1968AB07008ED995 /* Expression.swift */, + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */, + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */, + 1F1A742D1940169200FFFC47 /* Info.plist */, + 1FD8CD0C1968AB07008ED995 /* Matchers */, + 1F1A742E1940169200FFFC47 /* Nimble.h */, + 1FD8CD241968AB07008ED995 /* Utils */, + ); + name = Nimble; + path = Sources/Nimble; + sourceTree = ""; + }; + 1F1A74381940169200FFFC47 /* NimbleTests */ = { + isa = PBXGroup; + children = ( + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */, + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */, + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */, + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */, + 1FFD729A1963FC8200CD29A2 /* objc */, + 1F14FB61194180A7009F2A08 /* Helpers */, + 1F925EE3195C11B000ED456B /* Matchers */, + 1F1A74391940169200FFFC47 /* Supporting Files */, + ); + name = NimbleTests; + path = Tests/NimbleTests; + sourceTree = ""; + }; + 1F1A74391940169200FFFC47 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 1F1A743A1940169200FFFC47 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1F925EE3195C11B000ED456B /* Matchers */ = { + isa = PBXGroup; + children = ( + DD72EC631A93874A002F7651 /* AllPassTest.swift */, + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */, + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */, + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */, + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */, + 1F925EFB195C186800ED456B /* BeginWithTest.swift */, + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */, + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */, + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */, + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */, + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */, + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */, + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */, + 1F925EF8195C175000ED456B /* BeNilTest.swift */, + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */, + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */, + 1F925F01195C189500ED456B /* ContainTest.swift */, + 1F925EFE195C187600ED456B /* EndWithTest.swift */, + 1F925F04195C18B700ED456B /* EqualTest.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 */, + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */, + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD041968AB07008ED995 /* Adapters */ = { + isa = PBXGroup; + children = ( + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */, + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */, + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */, + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */, + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */, + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */, + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */, + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */, + ); + path = Adapters; + sourceTree = ""; + }; + 1FD8CD0C1968AB07008ED995 /* Matchers */ = { + isa = PBXGroup; + children = ( + DDB1BC781A92235600F743C3 /* AllPass.swift */, + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */, + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */, + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */, + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */, + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */, + 1FD8CD111968AB07008ED995 /* BeginWith.swift */, + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */, + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */, + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */, + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */, + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */, + 1FD8CD171968AB07008ED995 /* BeLogical.swift */, + 1FD8CD181968AB07008ED995 /* BeNil.swift */, + 1F91DD301C74BF61002C309F /* BeVoid.swift */, + 1FD8CD1A1968AB07008ED995 /* Contain.swift */, + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */, + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */, + 1FD8CD1C1968AB07008ED995 /* Equal.swift */, + 472FD1341B9E085700C7B8DA /* HaveCount.swift */, + DDB4D5EC19FE43C200E9D9FE /* Match.swift */, + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */, + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */, + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */, + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */, + 1FA0C3FE1E30B14500623165 /* Predicate.swift */, + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */, + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */, + 29EA59651B551EE6002D767E /* ThrowError.swift */, + 7A0A26221E7F52360092A34E /* ToSucceed.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD241968AB07008ED995 /* Utils */ = { + isa = PBXGroup; + children = ( + 1FD8CD251968AB07008ED995 /* Functional.swift */, + 1FD8CD261968AB07008ED995 /* Async.swift */, + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */, + 1FD8CD281968AB07008ED995 /* Stringers.swift */, + AE4BA9AC1C88DDB500B73906 /* Errors.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 1FFD729A1963FC8200CD29A2 /* objc */ = { + isa = PBXGroup; + children = ( + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */, + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */, + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */, + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */, + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */, + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */, + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */, + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */, + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */, + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */, + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */, + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */, + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */, + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */, + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */, + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */, + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */, + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */, + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = { + isa = PBXGroup; + children = ( + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */, + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */, + ); + name = "Carthage-Checkouts"; + path = Carthage/Checkouts; + sourceTree = ""; + }; + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */, + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */, + ); + name = CwlCatchException; + path = CwlCatchException/Sources; + sourceTree = ""; + }; + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */, + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */, + ); + name = CwlPreconditionTesting; + path = CwlPreconditionTesting/Sources; + sourceTree = ""; + }; + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */, + ); + path = CwlCatchException; + sourceTree = ""; + }; + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */ = { + isa = PBXGroup; + children = ( + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */, + CDFB6A211F7E07C600AD8CC7 /* include */, + ); + path = CwlCatchExceptionSupport; + sourceTree = ""; + }; + CDFB6A211F7E07C600AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */, + ); + path = include; + sourceTree = ""; + }; + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */, + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */, + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */, + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */, + CDFB6A2F1F7E082400AD8CC7 /* Mach */, + CDFB6A311F7E082400AD8CC7 /* Posix */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; + CDFB6A2F1F7E082400AD8CC7 /* Mach */ = { + isa = PBXGroup; + children = ( + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */, + ); + path = Mach; + sourceTree = ""; + }; + CDFB6A311F7E082400AD8CC7 /* Posix */ = { + isa = PBXGroup; + children = ( + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */, + ); + path = Posix; + sourceTree = ""; + }; + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = { + isa = PBXGroup; + children = ( + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */, + CDFB6A351F7E082400AD8CC7 /* include */, + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */, + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */, + ); + path = CwlMachBadInstructionHandler; + sourceTree = ""; + }; + CDFB6A351F7E082400AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */, + ); + path = include; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + 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 */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + 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; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F1A74281940169200FFFC47 /* Nimble-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */; + buildPhases = ( + 1F1A74241940169200FFFC47 /* Sources */, + 1F1A74251940169200FFFC47 /* Frameworks */, + 1F1A74261940169200FFFC47 /* Headers */, + 1F1A74271940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-iOS"; + productName = "Nimble-iOS"; + productReference = 1F1A74291940169200FFFC47 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */; + buildPhases = ( + 1F1A74301940169200FFFC47 /* Sources */, + 1F1A74311940169200FFFC47 /* Frameworks */, + 1F1A74321940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F1A74371940169200FFFC47 /* PBXTargetDependency */, + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */, + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */, + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */, + ); + name = "Nimble-iOSTests"; + productName = "Nimble-iOSTests"; + productReference = 1F1A74341940169200FFFC47 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */; + buildPhases = ( + 1F5DF1501BDCA0CE00C3A531 /* Sources */, + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */, + 1F5DF1521BDCA0CE00C3A531 /* Headers */, + 1F5DF1531BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-tvOS"; + productName = "Nimble-tvOS"; + productReference = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */; + buildPhases = ( + 1F5DF15A1BDCA0CE00C3A531 /* Sources */, + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */, + 1F5DF15C1BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */, + ); + name = "Nimble-tvOSTests"; + productName = "Nimble-tvOSTests"; + productReference = 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F925EAC195C0D6300ED456B /* Nimble-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */; + buildPhases = ( + 1F925EA8195C0D6300ED456B /* Sources */, + 1F925EA9195C0D6300ED456B /* Frameworks */, + 1F925EAA195C0D6300ED456B /* Headers */, + 1F925EAB195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-macOS"; + productName = "Nimble-macOS"; + productReference = 1F925EAD195C0D6300ED456B /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */; + buildPhases = ( + 1F925EB3195C0D6300ED456B /* Sources */, + 1F925EB4195C0D6300ED456B /* Frameworks */, + 1F925EB5195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */, + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */, + ); + name = "Nimble-macOSTests"; + productName = "Nimble-OSXTests"; + productReference = 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1F1A74201940169200FFFC47 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F925EAC195C0D6300ED456B; + }; + A8F2B2541E79A4AB005BDD17 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1F1A741F1940169200FFFC47; + productRefGroup = 1F1A742A1940169200FFFC47 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1F925EAC195C0D6300ED456B /* Nimble-macOS */, + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */, + 1F1A74281940169200FFFC47 /* Nimble-iOS */, + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */, + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */, + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */, + A8F2B2541E79A4AB005BDD17 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F1A74271940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74321940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1531BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15C1BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAB195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB5195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A8F2B2581E79A4B0005BDD17 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F1A74241940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */, + 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 */, + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */, + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */, + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */, + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */, + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */, + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 29EA59661B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */, + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */, + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */, + CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */, + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */, + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, + CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */, + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74301940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */, + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */, + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */, + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */, + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */, + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */, + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0A1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13B1B9E0CFE00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1501BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */, + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */, + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */, + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */, + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */, + 1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */, + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */, + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */, + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */, + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */, + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */, + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */, + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */, + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */, + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */, + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */, + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */, + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */, + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */, + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */, + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */, + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */, + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */, + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */, + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */, + CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */, + 1F5DF18C1BDCA0F500C3A531 /* Async.swift in Sources */, + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */, + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */, + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */, + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */, + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */, + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */, + CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, + 1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */, + 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15A1BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */, + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */, + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */, + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */, + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */, + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */, + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */, + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */, + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */, + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */, + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */, + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */, + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */, + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */, + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */, + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */, + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */, + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */, + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */, + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */, + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */, + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */, + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */, + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */, + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */, + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */, + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */, + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */, + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */, + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */, + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */, + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */, + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */, + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */, + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */, + 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 */, + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */, + CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */, + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 6CAEDD0C1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */, + CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */, + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */, + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */, + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */, + CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */, + CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA8195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */, + 1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */, + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */, + 1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */, + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */, + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */, + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */, + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */, + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */, + 29EA59671B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */, + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */, + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */, + CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */, + CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */, + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */, + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, + CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */, + 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB3195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.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 */, + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAC19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59641B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0B1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13A1B9E0A9F00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1F1A74371940169200FFFC47 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */; + }; + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */; + targetProxy = 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */; + }; + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */; + }; + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */; + }; + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F1A743D1940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1F1A743E1940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 1F1A74401940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + "$(inherited)", + ); + 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; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74411940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + ); + 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"; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 1F1A74431940169200FFFC47 /* Debug */ = { + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_CODE_SIGN_FLAGS = "--verbose"; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74441940169200FFFC47 /* Release */ = { + 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"; + 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"; + }; + name = Release; + }; + 1F5DF1661BDCA0CE00C3A531 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 1F5DF1671BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + 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 = ( + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Nimble; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F5DF1681BDCA0CE00C3A531 /* Debug */ = { + 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"; + 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; + }; + name = Debug; + }; + 1F5DF1691BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + 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"; + 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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F925EC1195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + 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 = { + 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)", + "$(inherited)", + ); + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-weak_framework", + XCTest, + "-weak-lswiftXCTest", + ); + 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; + }; + name = Release; + }; + 1F925EC4195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F925EC5195C0D6300ED456B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + A8F2B2551E79A4AB005BDD17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Debug; + }; + A8F2B2561E79A4AB005BDD17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A743D1940169200FFFC47 /* Debug */, + 1F1A743E1940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74401940169200FFFC47 /* Debug */, + 1F1A74411940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74431940169200FFFC47 /* Debug */, + 1F1A74441940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1661BDCA0CE00C3A531 /* Debug */, + 1F5DF1671BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1681BDCA0CE00C3A531 /* Debug */, + 1F5DF1691BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC1195C0D6300ED456B /* Debug */, + 1F925EC2195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC4195C0D6300ED456B /* Debug */, + 1F925EC5195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8F2B2551E79A4AB005BDD17 /* Debug */, + A8F2B2561E79A4AB005BDD17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F1A74201940169200FFFC47 /* Project object */; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..80405c9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..d640838 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..c45d780 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift new file mode 100644 index 0000000..8d0b745 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:3.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift new file mode 100644 index 0000000..740b842 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift @@ -0,0 +1,22 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + products: [ + .library(name: "Nimble", targets: ["Nimble"]), + ], + targets: [ + .target( + name: "Nimble", + dependencies: [] + ), + .testTarget( + name: "NimbleTests", + dependencies: ["Nimble"], + exclude: ["objc"] + ), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/README.md new file mode 100644 index 0000000..19c562f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/README.md @@ -0,0 +1,1764 @@ +# Nimble + +[![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) +[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble) + +Use Nimble to express the expected outcomes of Swift +or Objective-C expressions. Inspired by +[Cedar](https://github.com/pivotal/cedar). + +```swift +// Swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + +# How to Use Nimble + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest) +- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto) + - [Custom Failure Messages](#custom-failure-messages) + - [Type Safety](#type-safety) + - [Operator Overloads](#operator-overloads) + - [Lazily Computed Values](#lazily-computed-values) + - [C Primitives](#c-primitives) + - [Asynchronous Expectations](#asynchronous-expectations) + - [Objective-C Support](#objective-c-support) + - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand) +- [Built-in Matcher Functions](#built-in-matcher-functions) + - [Type Checking](#type-checking) + - [Equivalence](#equivalence) + - [Identity](#identity) + - [Comparisons](#comparisons) + - [Types/Classes](#typesclasses) + - [Truthiness](#truthiness) + - [Swift Assertions](#swift-assertions) + - [Swift Error Handling](#swift-error-handling) + - [Exceptions](#exceptions) + - [Collection Membership](#collection-membership) + - [Strings](#strings) + - [Collection Elements](#collection-elements) + - [Collection Count](#collection-count) + - [Notifications](#notifications) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) + - [Custom Validation](#custom-validation) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [PredicateResult](#predicateresult) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Basic Customization](#basic-customization) + - [Full Customization](#full-customization) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) + - [Migrating from the Old Matcher API](#migrating-from-the-old-matcher-api) + - [Minimal Step - Use `.predicate`](#minimal-step---use-predicate) + - [Convert to use `Predicate` Type with Old Matcher Constructor](#convert-to-use-predicate-type-with-old-matcher-constructor) + - [Convert to `Predicate` Type with Preferred Constructor](#convert-to-predicate-type-with-preferred-constructor) + - [Deprecation Roadmap](#deprecation-roadmap) +- [Installing Nimble](#installing-nimble) + - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule) + - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods) + - [Using Nimble without XCTest](#using-nimble-without-xctest) + + + +# Some Background: Expressing Outcomes Using Assertions in XCTest + +Apple's Xcode includes the XCTest framework, which provides +assertion macros to test whether code behaves properly. +For example, to assert that `1 + 1 = 2`, XCTest has you write: + +```swift +// Swift + +XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two") +``` + +Or, in Objective-C: + +```objc +// Objective-C + +XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two"); +``` + +XCTest assertions have a couple of drawbacks: + +1. **Not enough macros.** There's no easy way to assert that a string + contains a particular substring, or that a number is less than or + equal to another. +2. **It's hard to write asynchronous tests.** XCTest forces you to write + a lot of boilerplate code. + +Nimble addresses these concerns. + +# Nimble: Expectations Using `expect(...).to` + +Nimble allows you to express expectations using a natural, +easily understood language: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).to(equal("Squee!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).to(equal(@"Squee!")); +``` + +> The `expect` function autocompletes to include `file:` and `line:`, + but these parameters are optional. Use the default values to have + Xcode highlight the correct line when an expectation is not met. + +To perform the opposite expectation--to assert something is *not* +equal--use `toNot` or `notTo`: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).toNot(equal("Oh, hello there!")) +expect(seagull.squawk).notTo(equal("Oh, hello there!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).toNot(equal(@"Oh, hello there!")); +expect(seagull.squawk).notTo(equal(@"Oh, hello there!")); +``` + +## Custom Failure Messages + +Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text: + +```swift +// Swift + +expect(1 + 1).to(equal(3)) +// failed - expected to equal <3>, got <2> + +expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded") +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3>, got <2> +``` + +Or the *WithDescription version in Objective-C: + +```objc +// Objective-C + +@import Nimble; + +expect(@(1+1)).to(equal(@3)); +// failed - expected to equal <3.0000>, got <2.0000> + +expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded"); +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3.0000>, got <2.0000> +``` + +## Type Safety + +Nimble makes sure you don't compare two types that don't match: + +```swift +// Swift + +// Does not compile: +expect(1 + 1).to(equal("Squee!")) +``` + +> Nimble uses generics--only available in Swift--to ensure + type correctness. That means type checking is + not available when using Nimble in Objective-C. :sob: + +## Operator Overloads + +Tired of so much typing? With Nimble, you can use overloaded operators +like `==` for equivalence, or `>` for comparisons: + +```swift +// Swift + +// Passes if squawk does not equal "Hi!": +expect(seagull.squawk) != "Hi!" + +// Passes if 10 is greater than 2: +expect(10) > 2 +``` + +> Operator overloads are only available in Swift, so you won't be able + to use this syntax in Objective-C. :broken_heart: + +## Lazily Computed Values + +The `expect` function doesn't evaluate the value it's given until it's +time to match. So Nimble can test whether an expression raises an +exception once evaluated: + +```swift +// Swift + +// Note: Swift currently doesn't have exceptions. +// Only Objective-C code can raise exceptions +// that Nimble will catch. +// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064) +let exception = NSException( + name: NSInternalInconsistencyException, + reason: "Not enough fish in the sea.", + userInfo: ["something": "is fishy"]) +expect { exception.raise() }.to(raiseException()) + +// Also, you can customize raiseException to be more specific +expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException)) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea")) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea", + userInfo: ["something": "is fishy"])) +``` + +Objective-C works the same way, but you must use the `expectAction` +macro when making an expectation on an expression that has no return +value: + +```objc +// Objective-C + +NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Not enough fish in the sea." + userInfo:nil]; +expectAction(^{ [exception raise]; }).to(raiseException()); + +// Use the property-block syntax to be more specific. +expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException)); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea")); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea"). + userInfo(@{@"something": @"is fishy"})); + +// You can also pass a block for custom matching of the raised exception +expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(NSInternalInconsistencyException)); +})); +``` + +## C Primitives + +Some testing frameworks make it hard to test primitive C values. +In Nimble, it just works: + +```swift +// Swift + +let actual: CInt = 1 +let expectedValue: CInt = 1 +expect(actual).to(equal(expectedValue)) +``` + +In fact, Nimble uses type inference, so you can write the above +without explicitly specifying both types: + +```swift +// Swift + +expect(1 as CInt).to(equal(1)) +``` + +> In Objective-C, Nimble only supports Objective-C objects. To + make expectations on primitive C values, wrap then in an object + literal: + +```objc +expect(@(1 + 1)).to(equal(@2)); +``` + +## Asynchronous Expectations + +In Nimble, it's easy to make expectations on values that are updated +asynchronously. Just use `toEventually` or `toEventuallyNot`: + +```swift +// Swift 3.0 and later + +DispatchQueue.main.async { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```swift +// Swift 2.3 and earlier + +dispatch_async(dispatch_get_main_queue()) { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```objc +// Objective-C + +dispatch_async(dispatch_get_main_queue(), ^{ + [ocean add:@"dolphins"]; + [ocean add:@"whales"]; +}); +expect(ocean).toEventually(contain(@"dolphins", @"whales")); +``` + +Note: toEventually triggers its polls on the main thread. Blocking the main +thread will cause Nimble to stop the run loop. This can cause test pollution +for whatever incomplete code that was running on the main thread. Blocking the +main thread can be caused by blocking IO, calls to sleep(), deadlocks, and +synchronous IPC. + +In the above example, `ocean` is constantly re-evaluated. If it ever +contains dolphins and whales, the expectation passes. If `ocean` still +doesn't contain them, even after being continuously re-evaluated for one +whole second, the expectation fails. + +Sometimes it takes more than a second for a value to update. In those +cases, use the `timeout` parameter: + +```swift +// Swift + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).toEventually(contain("starfish"), timeout: 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) +``` + +```objc +// Objective-C + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).withTimeout(3).toEventually(contain(@"starfish")); +``` + +You can also provide a callback by using the `waitUntil` function: + +```swift +// Swift + +waitUntil { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +Note: `waitUntil` triggers its timeout code on the main thread. Blocking the main +thread will cause Nimble to stop the run loop to continue. This can cause test +pollution for whatever incomplete code that was running on the main thread. +Blocking the main thread can be caused by blocking IO, calls to sleep(), +deadlocks, and synchronous IPC. + +In some cases (e.g. when running on slower machines) it can be useful to modify +the default timeout and poll interval values. This can be done as follows: + +```swift +// Swift + +// Increase the global timeout to 5 seconds: +Nimble.AsyncDefaults.Timeout = 5 + +// Slow the polling interval to 0.1 seconds: +Nimble.AsyncDefaults.PollInterval = 0.1 +``` + +## Objective-C Support + +Nimble has full support for Objective-C. However, there are two things +to keep in mind when using Nimble in Objective-C: + +1. All parameters passed to the `expect` function, as well as matcher + functions like `equal`, must be Objective-C objects or can be converted into + an `NSObject` equivalent: + + ```objc + // Objective-C + + @import Nimble; + + expect(@(1 + 1)).to(equal(@2)); + expect(@"Hello world").to(contain(@"world")); + + // Boxed as NSNumber * + expect(2).to(equal(2)); + expect(1.2).to(beLessThan(2.0)); + expect(true).to(beTruthy()); + + // Boxed as NSString * + expect("Hello world").to(equal("Hello world")); + + // Boxed as NSRange + expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10))); + ``` + +2. To make an expectation on an expression that does not return a value, + such as `-[NSException raise]`, use `expectAction` instead of + `expect`: + + ```objc + // Objective-C + + expectAction(^{ [exception raise]; }).to(raiseException()); + ``` + +The following types are currently converted to an `NSObject` type: + + - **C Numeric types** are converted to `NSNumber *` + - `NSRange` is converted to `NSValue *` + - `char *` is converted to `NSString *` + +For the following matchers: + +- `equal` +- `beGreaterThan` +- `beGreaterThanOrEqual` +- `beLessThan` +- `beLessThanOrEqual` +- `beCloseTo` +- `beTrue` +- `beFalse` +- `beTruthy` +- `beFalsy` +- `haveCount` + +If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues). + +## Disabling Objective-C Shorthand + +Nimble provides a shorthand for expressing expectations using the +`expect` function. To disable this shorthand in Objective-C, define the +`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before +importing Nimble: + +```objc +#define NIMBLE_DISABLE_SHORT_SYNTAX 1 + +@import Nimble; + +NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!")); +``` + +> Disabling the shorthand is useful if you're testing functions with + names that conflict with Nimble functions, such as `expect` or + `equal`. If that's not the case, there's no point in disabling the + shorthand. + +# Built-in Matcher Functions + +Nimble includes a wide variety of matcher functions. + +## Type Checking + +Nimble supports checking the type membership of any kind of object, whether +Objective-C conformant or not: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// The following tests pass +expect(1).to(beAKindOf(Int.self)) +expect("turtle").to(beAKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beAKindOf(SomeProtocol.self)) +expect(classObject).to(beAKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beAKindOf(SomeProtocol.self)) +expect(structObject).to(beAKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAKindOf(SomeClassConformingToProtocol.self)) +``` + +```objc +// Objective-C + +// The following tests pass +NSMutableArray *array = [NSMutableArray array]; +expect(array).to(beAKindOf([NSArray class])); +expect(@1).toNot(beAKindOf([NSNull class])); +``` + +Objects can be tested for their exact types using the `beAnInstanceOf` matcher: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only +// passes if the object is the EXACT type requested. The following +// tests pass -- note its behavior when working in an inheritance hierarchy. +expect(1).to(beAnInstanceOf(Int.self)) +expect("turtle").to(beAnInstanceOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self)) +``` + +## Equivalence + +```swift +// Swift + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) +expect(actual) == expected + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +expect(actual) != expected +``` + +```objc +// Objective-C + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +``` + +Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`. +`equal` will always fail when used to compare one or more `nil` values. + +## Identity + +```swift +// Swift + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)) +expect(actual) === expected + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)) +expect(actual) !== expected +``` + +It is important to remember that `beIdenticalTo` only makes sense when comparing +types with reference semantics, which have a notion of identity. In Swift, +that means types that are defined as a `class`. + +This matcher will not work when comparing types with value semantics such as +those defined as a `struct` or `enum`. If you need to compare two value types, +consider what it means for instances of your type to be identical. This may mean +comparing individual properties or, if it makes sense to do so, conforming your type +to `Equatable` and using Nimble's equivalence matchers instead. + + +```objc +// Objective-C + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)); + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)); +``` + +## Comparisons + +```swift +// Swift + +expect(actual).to(beLessThan(expected)) +expect(actual) < expected + +expect(actual).to(beLessThanOrEqualTo(expected)) +expect(actual) <= expected + +expect(actual).to(beGreaterThan(expected)) +expect(actual) > expected + +expect(actual).to(beGreaterThanOrEqualTo(expected)) +expect(actual) >= expected +``` + +```objc +// Objective-C + +expect(actual).to(beLessThan(expected)); +expect(actual).to(beLessThanOrEqualTo(expected)); +expect(actual).to(beGreaterThan(expected)); +expect(actual).to(beGreaterThanOrEqualTo(expected)); +``` + +> Values given to the comparison matchers above must implement + `Comparable`. + +Because of how computers represent floating point numbers, assertions +that two floating point numbers be equal will sometimes fail. To express +that two numbers should be close to one another within a certain margin +of error, use `beCloseTo`: + +```swift +// Swift + +expect(actual).to(beCloseTo(expected, within: delta)) +``` + +```objc +// Objective-C + +expect(actual).to(beCloseTo(expected).within(delta)); +``` + +For example, to assert that `10.01` is close to `10`, you can write: + +```swift +// Swift + +expect(10.01).to(beCloseTo(10, within: 0.1)) +``` + +```objc +// Objective-C + +expect(@(10.01)).to(beCloseTo(@10).within(0.1)); +``` + +There is also an operator shortcut available in Swift: + +```swift +// Swift + +expect(actual) ≈ expected +expect(actual) ≈ (expected, delta) + +``` +(Type option+x to get `≈` on a U.S. keyboard) + +The former version uses the default delta of 0.0001. Here is yet another way to do this: + +```swift +// Swift + +expect(actual) ≈ expected ± delta +expect(actual) == expected ± delta + +``` +(Type option+shift+= to get `±` on a U.S. keyboard) + +If you are comparing arrays of floating point numbers, you'll find the following useful: + +```swift +// Swift + +expect([0.0, 2.0]) ≈ [0.0001, 2.0001] +expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1)) + +``` + +> Values given to the `beCloseTo` matcher must be coercable into a + `Double`. + +## Types/Classes + +```swift +// Swift + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)) + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)) +``` + +```objc +// Objective-C + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)); + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)); +``` + +> Instances must be Objective-C objects: subclasses of `NSObject`, + or Swift objects bridged to Objective-C with the `@objc` prefix. + +For example, to assert that `dolphin` is a kind of `Mammal`: + +```swift +// Swift + +expect(dolphin).to(beAKindOf(Mammal)) +``` + +```objc +// Objective-C + +expect(dolphin).to(beAKindOf([Mammal class])); +``` + +> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to + test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`. + +## Truthiness + +```swift +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()) + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()) + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()) + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()) + +// Passes if 'actual' is nil: +expect(actual).to(beNil()) +``` + +```objc +// Objective-C + +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()); + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()); + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()); + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()); + +// Passes if 'actual' is nil: +expect(actual).to(beNil()); +``` + +## Swift Assertions + +If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an assertion, +// such as by calling 'fatalError()' or if a precondition fails: +expect { try somethingThatThrows() }.to(throwAssertion()) +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing an NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the code after the precondition check is not run: +var reachedPoint1 = false +var reachedPoint2 = false +expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true +}.to(throwAssertion()) + +expect(reachedPoint1) == true +expect(reachedPoint2) == false +``` + +Notes: + +* This feature is only available in Swift. +* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_. +* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration. + +## Swift Error Handling + +If you're using Swift 2.0 or newer, you can use the `throwError` matcher to check if an error is thrown. + +Note: +The following code sample references the `Swift.Error` protocol. +This is `Swift.ErrorProtocol` in versions of Swift prior to version 3.0. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an 'Error': +expect { try somethingThatThrows() }.to(throwError()) + +// Passes if 'somethingThatThrows()' throws an error within a particular domain: +expect { try somethingThatThrows() }.to(throwError { (error: Error) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if 'somethingThatThrows()' throws a particular error enum case: +expect { try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if 'somethingThatThrows()' throws an error of a particular type: +expect { try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +When working directly with `Error` values, using the `matchError` matcher +allows you to perform certain checks on the error itself without having to +explicitly cast the error. + +The `matchError` matcher allows you to check whether or not the error: + +- is the same _type_ of error you are expecting. +- represents a particular error value that you are expecting. + +This can be useful when using `Result` or `Promise` types, for example. + +```swift +// Swift + +let actual: Error = ... + +// Passes if 'actual' represents any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.self)) + +// Passes if 'actual' represents the case 'timeout' from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.timeout)) + +// Passes if 'actual' contains an NSError equal to the one provided: +expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil))) +``` + +Note: This feature is only available in Swift. + +## Exceptions + +```swift +// Swift + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name: +expect(actual).to(raiseException(named: name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException(named: name, reason: reason)) + +// Passes if 'actual' raises an exception which passes expectations defined in the given closure: +// (in this case, if the exception's name begins with "a r") +expect { exception.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(beginWith("a r")) +}) +``` + +```objc +// Objective-C + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name +expect(actual).to(raiseException().named(name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException().named(name).reason(reason)) + +// Passes if 'actual' raises an exception and it passes expectations defined in the given block: +// (in this case, if name begins with "a r") +expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(@"a r")); +})); +``` + +Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)). +Only Objective-C code can raise exceptions that Nimble will catch. + +## Collection Membership + +```swift +// Swift + +// Passes if all of the expected values are members of 'actual': +expect(actual).to(contain(expected...)) + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()) +``` + +```objc +// Objective-C + +// Passes if expected is a member of 'actual': +expect(actual).to(contain(expected)); + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()); +``` + +> In Swift `contain` takes any number of arguments. The expectation + passes if all of them are members of the collection. In Objective-C, + `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27). + +For example, to assert that a list of sea creature names contains +"dolphin" and "starfish": + +```swift +// Swift + +expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish")) +``` + +```objc +// Objective-C + +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin")); +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish")); +``` + +> `contain` and `beEmpty` expect collections to be instances of + `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements. + +To test whether a set of elements is present at the beginning or end of +an ordered collection, use `beginWith` and `endWith`: + +```swift +// Swift + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected...)) + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected...)) +``` + +```objc +// Objective-C + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected)); + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected)); +``` + +> `beginWith` and `endWith` expect collections to be instances of + `NSArray`, or ordered Swift collections composed of `Equatable` + elements. + + Like `contain`, in Objective-C `beginWith` and `endWith` only support + a single argument [for now](https://github.com/Quick/Nimble/issues/27). + +For code that returns collections of complex objects without a strict +ordering, there is the `containElementSatisfying` matcher: + +```swift +// Swift + +struct Turtle { + let color: String +} + +let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "green" +})) +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "blue" +}, "that is a turtle with color 'blue'")) + +// The second matcher will incorporate the provided string in the error message +// should it fail +``` + +```objc +// Objective-C + +@interface Turtle : NSObject +@property (nonatomic, readonly, nonnull) NSString *color; +@end + +@implementation Turtle +@end + +NSArray * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(substring)) + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)) + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)) + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()) + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(expected)); + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)); + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)); + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()); + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +## Collection Elements + +Nimble provides a means to check that all elements of a collection pass a given expectation. + +### Swift + +In Swift, the collection must be an instance of a type conforming to +`Sequence`. + +```swift +// Swift + +// Providing a custom function: +expect([1, 2, 3, 4]).to(allPass { $0! < 5 }) + +// Composing the expectation with another matcher: +expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) +``` + +### Objective-C + +In Objective-C, the collection must be an instance of a type which implements +the `NSFastEnumeration` protocol, and whose elements are instances of a type +which subclasses `NSObject`. + +Additionally, unlike in Swift, there is no override to specify a custom +matcher function. + +```objc +// Objective-C + +expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@5))); +``` + +## Collection Count + +```swift +// Swift + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +For Swift, the actual value must be an instance of a type conforming to `Collection`. +For example, instances of `Array`, `Dictionary`, or `Set`. + +For Objective-C, the actual value must be one of the following classes, or their subclasses: + + - `NSArray`, + - `NSDictionary`, + - `NSSet`, or + - `NSHashTable`. + +## Notifications + +```swift +// Swift +let testNotification = Notification(name: "Foo", object: nil) + +// passes if the closure in expect { ... } posts a notification to the default +// notification center. +expect { + NotificationCenter.default.postNotification(testNotification) +}.to(postNotifications(equal([testNotification])) + +// 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)) +``` + +> This matcher is only available in Swift. + +## Matching a value to any of a group of matchers + +```swift +// Swift + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7))) + +// in Swift you also have the option to use the || operator to achieve a similar function +expect(82).to(beLessThan(50) || beGreaterThan(80)) +``` + +```objc +// Objective-C + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7))) +``` + +Note: This matcher allows you to chain any number of matchers together. This provides flexibility, + but if you find yourself chaining many matchers together in one test, consider whether you + could instead refactor that single test into multiple, more precisely focused tests for + better coverage. + +## Custom Validation + +```swift +// Swift + +// passes if .succeeded is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).to(succeed()) + +// passes if .failed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).notTo(succeed()) +``` + +The `String` provided with `.failed()` is shown when the test fails. + +When using `toEventually()` be careful not to make state changes or run process intensive code since this closure will be ran many times. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `Predicate` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> Predicate { + // Can be shortened to: + // Predicate { actual in ... } + // + // But shown with types here for clarity. + return Predicate { (actual: Expression) throws -> PredicateResult in + let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>") + if let actualValue = try actualExpression.evaluate() { + return PredicateResult( + bool: actualValue == expectedValue!, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} +``` + +The return value of a `Predicate` closure is a `PredicateResult` that indicates +whether the actual value matches the expectation and what error message to +display on failure. + +> The actual `equal` matcher function does not match when + `expected` are nil; the example above has been edited for brevity. + +Since matchers are just Swift functions, you can define them anywhere: +at the top of your test file, in a file shared by all of your tests, or +in an Xcode project you distribute to others. + +> If you write a matcher you think everyone can use, consider adding it + to Nimble's built-in set of matchers by sending a pull request! Or + distribute it yourself via GitHub. + +For examples of how to write your own matchers, just check out the +[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers) +to see how Nimble's built-in set of matchers are implemented. You can +also check out the tips below. + +## PredicateResult + +`PredicateResult` is the return struct that `Predicate` return to indicate +success and failure. A `PredicateResult` is made up of two values: +`PredicateStatus` and `ExpectationMessage`. + +Instead of a boolean, `PredicateStatus` captures a trinary set of values: + +```swift +// Swift + +public enum PredicateStatus { +// The predicate "passes" with the given expression +// eg - expect(1).to(equal(1)) +case matches + +// The predicate "fails" with the given expression +// eg - expect(1).toNot(equal(1)) +case doesNotMatch + +// The predicate never "passes" with the given expression, even if negated +// eg - expect(nil as Int?).toNot(equal(1)) +case fail + +// ... +} +``` + +Meanwhile, `ExpectationMessage` provides messaging semantics for error reporting. + +```swift +// Swift + +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// ... +} +``` + +Predicates should usually depend on either `.expectedActualValueTo(..)` or +`.fail(..)` when reporting errors. Special cases can be used for the other enum +cases. + +Finally, if your Predicate utilizes other Predicates, you can utilize +`.appended(details:)` and `.appended(message:)` methods to annotate an existing +error with more details. + +A common message to append is failing on nils. For that, `.appendedBeNilHint()` +can be used. + +## Lazy Evaluation + +`actualExpression` is a lazy, memoized closure around the value provided to the +`expect` function. The expression can either be a closure or a value directly +passed to `expect(...)`. In order to determine whether that value matches, +custom matchers should call `actualExpression.evaluate()`: + +```swift +// Swift + +public func beNil() -> Predicate { + // Predicate.simpleNilable(..) automatically generates ExpectationMessage for + // us based on the string we provide to it. Also, the 'Nilable' postfix indicates + // that this Predicate supports matching against nil actualExpressions, instead of + // always resulting in a PredicateStatus.fail result -- which is true for + // Predicate.simple(..) + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} +``` + +In the above example, `actualExpression` is not `nil` -- it is a closure +that returns a value. The value it returns, which is accessed via the +`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil` +matcher function returns `true`, indicating that the expectation passed. + +## Type Checking via Swift Generics + +Using Swift's generics, matchers can constrain the type of the actual value +passed to the `expect` function by modifying the return type. + +For example, the following matcher, `haveDescription`, only accepts actual +values that implement the `Printable` protocol. It checks their `description` +against the one provided to the matcher function, and passes if they are the same: + +```swift +// Swift + +public func haveDescription(description: String) -> Predicate { + return Predicate.simple("have description") { actual in + return PredicateStatus(bool: actual.evaluate().description == description) + } +} +``` + +## Customizing Failure Messages + +When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble +outputs the following failure message when an expectation fails: + +```swift +// where `message` is the first string argument and +// `actual` is the actual value received in `expect(..)` +"expected to \(message), got <\(actual)>" +``` + +You can customize this message by modifying the way you create a `Predicate`. + +### Basic Customization + +For slightly more complex error messaging, receive the created failure message +with `Predicate.define(..)`: + +```swift +// Swift + +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(bool: matches, message: msg) + } +} +``` + +In the example above, `msg` is defined based on the string given to +`Predicate.define`. The code looks akin to: + +```swift +// Swift + +let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedValue))>") +``` + +### Full Customization + +To fully customize the behavior of the Predicate, use the overload that expects +a `PredicateResult` to be returned. + +Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use: + +```swift +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// Emits standard error message with a custom actual value instead of the default. +// eg - "expected to , got " +case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + +// Emits standard error message without mentioning the actual value +// eg - "expected to " +case expectedTo(/* message: */ String) + +// ... +} +``` + +For matchers that compose other matchers, there are a handful of helper +functions to annotate messages. + +`appended(message: String)` is used to append to the original failure message: + +```swift +// produces "expected to be true, got (use beFalse() for inverse)" +// appended message do show up inline in Xcode. +.expectedActualValueTo("be true").appended(message: " (use beFalse() for inverse)") +``` + +For a more comprehensive message that spans multiple lines, use +`appended(details: String)` instead: + +```swift +// produces "expected to be true, got \n\nuse beFalse() for inverse\nor use beNil()" +// details do not show inline in Xcode, but do show up in test logs. +.expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()") +``` + +## 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 +custom matcher. The example below defines the class method +`+[NMBObjCMatcher 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) + } + } +} +``` + +The above allows you to use the matcher from Objective-C: + +```objc +// Objective-C + +expect(actual).to([NMBObjCMatcher beNilMatcher]()); +``` + +To make the syntax easier to use, define a C function that calls the +class method: + +```objc +// Objective-C + +FOUNDATION_EXPORT id beNil() { + return [NMBObjCMatcher beNilMatcher]; +} +``` + +### Properly Handling `nil` in Objective-C Matchers + +When supporting Objective-C, make sure you handle `nil` appropriately. +Like [Cedar](https://github.com/pivotal/cedar/issues/100), +**most matchers do not match with nil**. This is to bring prevent test +writers from being surprised by `nil` values where they did not expect +them. + +Nimble provides the `beNil` matcher function for test writer that want +to make expectations on `nil` objects: + +```objc +// Objective-C + +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. + +```swift + +public func beginWith(startingElement: T) -> NonNilMatcherFunc { + 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 + } +} + +extension NMBObjCMatcher { + public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.evaluate() + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } +} +``` + +## Migrating from the Old Matcher API + +Previously (`<7.0.0`), Nimble supported matchers via the following types: + +- `Matcher` +- `NonNilMatcherFunc` +- `MatcherFunc` + +All of those types have been replaced by `Predicate`. While migrating can be a +lot of work, Nimble currently provides several steps to aid migration of your +custom matchers: + +### Minimal Step - Use `.predicate` + +Nimble provides an extension to the old types that automatically naively +converts those types to the newer `Predicate`. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + 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 + }.predicate +} +``` + +This is the simpliest way to externally support `Predicate` which allows easier +composition than the old Nimble matcher interface, with minimal effort to change. + +### Convert to use `Predicate` Type with Old Matcher Constructor + +The second most convenient step is to utilize special constructors that +`Predicate` supports that closely align to the constructors of the old Nimble +matcher types. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} +``` + +This allows you to completely drop the old types from your code, although the +intended behavior may alter slightly to what is desired. + +### Convert to `Predicate` Type with Preferred Constructor + +Finally, you can convert to the native `Predicate` format using one of the +constructors not used to assist in the migration. + +### Deprecation Roadmap + +Nimble 7 introduces `Predicate` but will support the old types with warning +deprecations. A couple major releases of Nimble will remain backwards +compatible with the old matcher api, although new features may not be +backported. + +The deprecating plan is a 3 major versions removal. Which is as follows: + + 1. Introduce new `Predicate` API, deprecation warning for old matcher APIs. + (Nimble `v7.x.x`) + 2. Introduce warnings on migration-path features (`.predicate`, + `Predicate`-constructors with similar arguments to old API). (Nimble + `v8.x.x`) + 3. Remove old API. (Nimble `v9.x.x`) + + +# Installing Nimble + +> Nimble can be used on its own, or in conjunction with its sister + project, [Quick](https://github.com/Quick/Quick). To install both + Quick and Nimble, follow [the installation instructions in the Quick + Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md). + +Nimble can currently be installed in one of two ways: using CocoaPods, or with +git submodules. + +## Installing Nimble as a Submodule + +To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow +these 4 easy steps: + +1. Clone the Nimble repository +2. Add Nimble.xcodeproj to the Xcode workspace for your project +3. Link Nimble.framework to your test target +4. Start writing expectations! + +For more detailed instructions on each of these steps, +read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick). +Ignore the steps involving adding Quick to your project in order to +install just Nimble. + +## Installing Nimble via CocoaPods + +To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add +Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift +support for CocoaPods. + +```ruby +platform :ios, '8.0' + +source 'https://github.com/CocoaPods/Specs.git' + +# Whatever pods you need for your app go here + +target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do + use_frameworks! + pod 'Nimble', '~> 6.0.0' +end +``` + +Finally run `pod install`. + +## Using Nimble without XCTest + +Nimble is integrated with XCTest to allow it work well when used in Xcode test +bundles, however it can also be used in a standalone app. After installing +Nimble using one of the above methods, there are two additional steps required +to make this work. + +1. Create a custom assertion handler and assign an instance of it to the + global `NimbleAssertionHandler` variable. For example: + +```swift +class MyAssertionHandler : AssertionHandler { + func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) { + if (!assertion) { + print("Expectation failed: \(message.stringValue)") + } + } +} +``` +```swift +// Somewhere before you use any assertions +NimbleAssertionHandler = MyAssertionHandler() +``` + +2. Add a post-build action to fix an issue with the Swift XCTest support + library being unnecessarily copied into your app + * Edit your scheme in Xcode, and navigate to Build -> Post-actions + * Click the "+" icon and select "New Run Script Action" + * Open the "Provide build settings from" dropdown and select your target + * Enter the following script contents: +``` +rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib" +``` + +You can now use Nimble assertions in your code and handle failures as you see +fit. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift @@ -0,0 +1,17 @@ +import Foundation + +/// Protocol for the assertion handler that Nimble uses for all expectations. +public protocol AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) +} + +/// Global backing interface for assertions that Nimble creates. +/// Defaults to a private test handler that passes through to XCTest. +/// +/// If XCTest is not available, you must assign your own assertion handler +/// before using any matchers, otherwise Nimble will abort the program. +/// +/// @see AssertionHandler +public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in + return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() +}() diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift @@ -0,0 +1,19 @@ +/// AssertionDispatcher allows multiple AssertionHandlers to receive +/// assertion messages. +/// +/// @warning Does not fully dispatch if one of the handlers raises an exception. +/// This is possible with XCTest-based assertion handlers. +/// +public class AssertionDispatcher: AssertionHandler { + let handlers: [AssertionHandler] + + public init(handlers: [AssertionHandler]) { + self.handlers = handlers + } + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + for handler in handlers { + handler.assert(assertion, message: message, location: location) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift @@ -0,0 +1,100 @@ +import Foundation + +/// A data structure that stores information about an assertion when +/// AssertionRecorder is set as the Nimble assertion handler. +/// +/// @see AssertionRecorder +/// @see AssertionHandler +public struct AssertionRecord: CustomStringConvertible { + /// Whether the assertion succeeded or failed + public let success: Bool + /// The failure message the assertion would display on failure. + public let message: FailureMessage + /// The source location the expectation occurred on. + public let location: SourceLocation + + public var description: String { + return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" + } +} + +/// An AssertionHandler that silently records assertions that Nimble makes. +/// This is useful for testing failure messages for matchers. +/// +/// @see AssertionHandler +public class AssertionRecorder: AssertionHandler { + /// All the assertions that were captured by this recorder + public var assertions = [AssertionRecord]() + + public init() {} + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + assertions.append( + AssertionRecord( + success: assertion, + message: message, + location: location)) + } +} + +/// Allows you to temporarily replace the current Nimble assertion handler with +/// the one provided for the scope of the closure. +/// +/// Once the closure finishes, then the original Nimble assertion handler is restored. +/// +/// @see AssertionHandler +public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) { + let environment = NimbleEnvironment.activeInstance + let oldRecorder = environment.assertionHandler + let capturer = NMBExceptionCapture(handler: nil, finally: ({ + environment.assertionHandler = oldRecorder + })) + environment.assertionHandler = tempAssertionHandler + capturer.tryBlock { + try! closure() + } +} + +/// Captures expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about expectations +/// that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherFailingExpectations +public func gatherExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler + let recorder = AssertionRecorder() + let handlers: [AssertionHandler] + + if silently { + handlers = [recorder] + } else { + handlers = [recorder, previousRecorder] + } + + let dispatcher = AssertionDispatcher(handlers: handlers) + withAssertionHandler(dispatcher, closure: closure) + return recorder.assertions +} + +/// Captures failed expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about failed +/// expectations that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherExpectations +/// @see raiseException source for an example use case. +public func gatherFailingExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let assertions = gatherExpectations(silently: silently, closure: closure) + return assertions.filter { assertion in + !assertion.success + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..88d9406 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,187 @@ +import Foundation + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +private func from(objcPredicate: NMBPredicate) -> Predicate { + return Predicate { actualExpression in + let result = objcPredicate.satisfies(({ try! actualExpression.evaluate() }), + location: actualExpression.location) + return result.toSwift() + } +} + +internal struct ObjCMatcherWrapper: Matcher { + let matcher: NMBMatcher + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.matches( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.doesNotMatch( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } +} + +// Equivalent to Expectation, but for Nimble's Objective-C interface +public class NMBExpectation: NSObject { + internal let _actualBlock: () -> NSObject! + internal var _negative: Bool + internal let _file: FileString + internal let _line: UInt + internal var _timeout: TimeInterval = 1.0 + + @objc public init(actualBlock: @escaping () -> NSObject!, negative: Bool, file: FileString, line: UInt) { + self._actualBlock = actualBlock + self._negative = negative + self._file = file + self._line = line + } + + private var expectValue: Expectation { + return expect(_file, line: _line) { + self._actualBlock() as NSObject? + } + } + + @objc public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + @objc public var to: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.to(from(objcPredicate: pred)) + } else { + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toNot(from(objcPredicate: pred)) + } else { + self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toNotWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var notTo: (NMBMatcher) -> Void { return toNot } + + @objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + @objc public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toNotEventually: (NMBMatcher) -> Void { + return toEventuallyNot + } + + @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { + return toEventuallyNotWithDescription + } + + @objc public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..9ba2ffa --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,83 @@ +import Foundation + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +// swiftlint:disable line_length +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool +// swiftlint:enable line_length + +public class NMBObjCMatcher: NSObject, NMBMatcher { + let _match: MatcherBlock + let _doesNotMatch: MatcherBlock + let canMatchNil: Bool + + public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { + self.canMatchNil = canMatchNil + self._match = matcher + self._doesNotMatch = notMatcher + } + + public convenience init(matcher: @escaping MatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in + return !matcher(actualExpression, failureMessage) + })) + } + + public convenience init(matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, false) + }), notMatcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, true) + })) + } + + private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + do { + if !canMatchNil { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return false + } + } + } catch let error { + failureMessage.actualValue = "an unexpected error thrown: \(error)" + return false + } + return true + } + + public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _match( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _doesNotMatch( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..e1b5432 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift @@ -0,0 +1,45 @@ +import Dispatch +import Foundation + +/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this +/// class' existence +internal class NimbleEnvironment { + static var activeInstance: NimbleEnvironment { + get { + let env = Thread.current.threadDictionary["NimbleEnvironment"] + if let env = env as? NimbleEnvironment { + return env + } else { + let newEnv = NimbleEnvironment() + self.activeInstance = newEnv + return newEnv + } + } + set { + Thread.current.threadDictionary["NimbleEnvironment"] = newValue + } + } + + // TODO: eventually migrate the global to this environment value + var assertionHandler: AssertionHandler { + get { return NimbleAssertionHandler } + set { NimbleAssertionHandler = newValue } + } + + var suppressTVOSAssertionWarning: Bool = false + var awaiter: Awaiter + + init() { + let timeoutQueue: DispatchQueue + if #available(OSX 10.10, *) { + timeoutQueue = DispatchQueue.global(qos: .userInitiated) + } else { + timeoutQueue = DispatchQueue.global(priority: .high) + } + + awaiter = Awaiter( + waitLock: AssertionWaitLock(), + asyncQueue: .main, + timeoutQueue: timeoutQueue) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..0ad8590 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,81 @@ +import Foundation +import XCTest + +/// Default handler for Nimble. This assertion handler passes failures along to +/// XCTest. +public class NimbleXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + recordFailure("\(message.stringValue)\n", location: location) + } + } +} + +/// Alternative handler for Nimble. This assertion handler passes failures along +/// to XCTest by attempting to reduce the failure message size. +public class NimbleShortXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + let msg: String + if let actual = message.actualValue { + msg = "got: \(actual) \(message.postfixActual)" + } else { + msg = "expected \(message.to) \(message.postfixMessage)" + } + recordFailure("\(msg)\n", location: location) + } + } +} + +/// Fallback handler in case XCTest is unavailable. This assertion handler will abort +/// the program if it is invoked. +class NimbleXCTestUnavailableHandler: AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") + } +} + +#if !SWIFT_PACKAGE +/// Helper class providing access to the currently executing XCTestCase instance, if any +@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { + @objc static let sharedInstance = CurrentTestCaseTracker() + + private(set) var currentTestCase: XCTestCase? + + @objc func testCaseWillStart(_ testCase: XCTestCase) { + currentTestCase = testCase + } + + @objc func testCaseDidFinish(_ testCase: XCTestCase) { + currentTestCase = nil + } +} +#endif + +func isXCTestAvailable() -> Bool { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // XCTest is weakly linked and so may not be present + return NSClassFromString("XCTestCase") != nil +#else + return true +#endif +} + +private func recordFailure(_ message: String, location: SourceLocation) { +#if SWIFT_PACKAGE + XCTFail("\(message)", file: location.file, line: location.line) +#else + if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { + #if swift(>=4) + let line = Int(location.line) + #else + let line = location.line + #endif + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..8f8d360 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) +// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy +class NSException {} +#endif + +// NOTE: This file is not intended to be included in the Xcode project. It +// is picked up by the Swift Package Manager during its build process. + +/// A dummy reimplementation of the `NMBExceptionCapture` class to serve +/// as a stand-in for build and runtime environments that don't support +/// Objective C. +internal class ExceptionCapture { + let finally: (() -> Void)? + + init(handler: ((NSException) -> Void)?, finally: (() -> Void)?) { + self.finally = finally + } + + func tryBlock(_ unsafeBlock: (() -> Void)) { + // We have no way of handling Objective C exceptions in Swift, + // so we just go ahead and run the unsafeBlock as-is + unsafeBlock() + + finally?() + } +} + +/// Compatibility with the actual Objective-C implementation +typealias NMBExceptionCapture = ExceptionCapture diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..e874136 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,116 @@ +import Dispatch +import Foundation + +private enum ErrorResult { + case exception(NSException) + case error(Error) + case none +} + +/// Only classes, protocols, methods, properties, and subscript declarations can be +/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style +/// asynchronous waiting logic so that it may be called from Objective-C and Swift. +internal class NMBWait: NSObject { +// About these kind of lines, `@objc` attributes are only required for Objective-C +// support, so that should be conditional on Darwin platforms and normal Xcode builds +// (non-SwiftPM builds). +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#else + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#endif + + // Using a throwable closure makes this method not objc compatible. + internal class func throwableUntil( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) throws -> Void) { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + // swiftlint:disable:next line_length + let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in + DispatchQueue.main.async { + let capture = NMBExceptionCapture( + handler: ({ exception in + done(.exception(exception)) + }), + finally: ({ }) + ) + capture.tryBlock { + do { + try action { + done(.none) + } + } catch let e { + done(.error(e)) + } + } + } + }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line) + + switch result { + case .incomplete: internalError("Reached .incomplete state for waitUntil(...).") + case .blockedRunLoop: + 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) + case let .raisedException(exception): + fail("Unexpected exception raised: \(exception)") + case let .errorThrown(error): + fail("Unexpected error thrown: \(error)") + case .completed(.exception(let exception)): + fail("Unexpected exception raised: \(exception)") + case .completed(.error(let error)): + fail("Unexpected error thrown: \(error)") + case .completed(.none): // success + break + } + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#else + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> 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." +} + +/// Wait asynchronously until the done closure is called or the timeout has been reached. +/// +/// @discussion +/// Call the done() closure to indicate the waiting has completed. +/// +/// 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) { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..e49bb0c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1,64 @@ +import Foundation + +/// Make an expectation on a given actual value. The value given is lazily evaluated. +public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { + 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: @escaping () throws -> T?) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Always fails the test with a message and a specified location. +public func fail(_ message: String, location: SourceLocation) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(false, message: FailureMessage(stringValue: message), location: location) +} + +/// Always fails the test with a message. +public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { + fail(message, location: SourceLocation(file: file, line: line)) +} + +/// Always fails the test. +public func fail(_ file: FileString = #file, line: UInt = #line) { + fail("fail() always fails", file: file, line: line) +} + +/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts +internal func nimblePrecondition( + _ expr: @autoclosure() -> Bool, + _ name: @autoclosure() -> String, + _ message: @autoclosure() -> String, + file: StaticString = #file, + line: UInt = #line) { + let result = expr() + if !result { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let e = NSException( + name: NSExceptionName(name()), + reason: message(), + userInfo: nil) + e.raise() +#else + preconditionFailure("\(name()) - \(message())", file: file, line: line) +#endif + } +} + +internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { + fatalError( + "Nimble Bug Found: \(msg) at \(file):\(line).\n" + + "Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " + + "code snippet that caused this error." + ) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..e3f616a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,132 @@ +import Foundation + +// Deprecated +internal func expressionMatches(_ expression: Expression, matcher: U, to: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let pass = try matcher.matches(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +// Deprecated +internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = toNot + do { + let pass = try matcher.doesNotMatch(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { + func run() -> (Bool, FailureMessage) { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let result = try predicate.satisfies(expression) + result.message.update(failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (result.toBoolean(expectation: style), msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } + } + + var result: (Bool, FailureMessage) = (false, FailureMessage()) + if captureExceptions { + let capture = NMBExceptionCapture(handler: ({ exception -> Void in + let msg = FailureMessage() + msg.stringValue = "unexpected exception raised: \(exception)" + result = (false, msg) + }), finally: nil) + capture.tryBlock { + result = run() + } + } else { + result = run() + } + + return result +} + +public struct Expectation { + + public let expression: Expression + + public func verify(_ pass: Bool, _ message: FailureMessage) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(pass, message: message, location: expression.location) + } + + ////////////////// OLD API ///////////////////// + + /// DEPRECATED: Tests the actual value using a matcher to match. + public func to(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionMatches(expression, matcher: matcher, to: "to", description: description) + verify(pass, msg) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + 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) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + toNot(matcher, description: description) + } + + ////////////////// NEW API ///////////////////// + + /// Tests the actual value using a matcher to match. + public func to(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ predicate: Predicate, description: String? = nil) { + toNot(predicate, description: description) + } + + // see: + // - AsyncMatcherWrapper for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift new file mode 100644 index 0000000..992ee0e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift @@ -0,0 +1,262 @@ +import Foundation + +public indirect enum ExpectationMessage { + // --- Primary Expectations --- + /// includes actual value in output ("expected to , got ") + case expectedActualValueTo(/* message: */ String) + /// uses a custom actual value string in output ("expected to , got ") + case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + /// excludes actual value in output ("expected to ") + case expectedTo(/* message: */ String) + /// allows any free-form message ("") + case fail(/* message: */ String) + + // --- Composite Expectations --- + // Generally, you'll want the methods, appended(message:) and appended(details:) instead. + + /// Not Fully Implemented Yet. + case prepends(/* Prepended Message */ String, ExpectationMessage) + + /// appends after an existing message (" (use beNil() to match nils)") + case appends(ExpectationMessage, /* Appended Message */ String) + + /// provides long-form multi-line explainations ("\n\n") + case details(ExpectationMessage, String) + + internal var sampleMessage: String { + let asStr = toString(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. + public var expectedMessage: String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return msg + case let .expectedActualValueTo(msg): + return msg + case let .expectedCustomValueTo(msg, _): + return msg + case let .prepends(_, expectation): + return expectation.expectedMessage + case let .appends(expectation, msg): + return "\(expectation.expectedMessage)\(msg)" + case let .details(expectation, _): + return expectation.expectedMessage + } + } + + /// Appends a message after the primary expectation message + public func appended(message: String) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo, .appends, .prepends: + return .appends(self, message) + case let .details(expectation, msg): + return .details(expectation.appended(message: message), msg) + } + } + + /// Appends a message hinting to use beNil() for when the actual value given was nil. + public func appendedBeNilHint() -> ExpectationMessage { + return appended(message: " (use beNil() to match nils)") + } + + /// Appends a detailed (aka - multiline) message after the primary expectation message + /// Detailed messages will be placed after .appended(message:) calls. + public func appended(details: String) -> ExpectationMessage { + return .details(self, details) + } + + internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(self) + case let .prepends(msg, expectation): + return .prepends(msg, expectation.visitLeafs(f)) + case let .appends(expectation, msg): + return .appends(expectation.visitLeafs(f), msg) + case let .details(expectation, msg): + return .details(expectation.visitLeafs(f), msg) + } + } + + /// Replaces a primary expectation with one returned by f. Preserves all composite expectations + /// that were built upon it (aka - all appended(message:) and appended(details:). + public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(msg) + default: + return msg + } + } + return visitLeafs(walk) + } + + /// Wraps a primary expectation with text before and after it. + /// Alias to prepended(message: before).appended(message: after) + public func wrappedExpectation(before: String, after: String) -> ExpectationMessage { + return prepended(expectation: before).appended(message: after) + } + + /// Prepends a message by modifying the primary expectation + public func prepended(expectation message: String) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case let .expectedTo(msg): + return .expectedTo(message + msg) + case let .expectedActualValueTo(msg): + return .expectedActualValueTo(message + msg) + case let .expectedCustomValueTo(msg, actual): + return .expectedCustomValueTo(message + msg, actual) + default: + return msg.visitLeafs(walk) + } + } + return visitLeafs(walk) + } + + // TODO: test & verify correct behavior + internal func prepended(message: String) -> ExpectationMessage { + return .prepends(message, self) + } + + /// Converts the tree of ExpectationMessages into a final built string. + public func toString(actual: String, expected: String = "expected", to: String = "to") -> String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return "\(expected) \(to) \(msg)" + case let .expectedActualValueTo(msg): + return "\(expected) \(to) \(msg), got \(actual)" + case let .expectedCustomValueTo(msg, actual): + return "\(expected) \(to) \(msg), got \(actual)" + case let .prepends(msg, expectation): + return "\(msg)\(expectation.toString(actual: actual, expected: expected, to: to))" + case let .appends(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\(msg)" + case let .details(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\n\n\(msg)" + } + } + + // Backwards compatibility: converts ExpectationMessage tree to FailureMessage + internal func update(failureMessage: FailureMessage) { + switch self { + case let .fail(msg): + failureMessage.stringValue = msg + case let .expectedTo(msg): + failureMessage.actualValue = nil + failureMessage.postfixMessage = msg + case let .expectedActualValueTo(msg): + failureMessage.postfixMessage = msg + case let .expectedCustomValueTo(msg, actual): + failureMessage.postfixMessage = msg + failureMessage.actualValue = actual + case let .prepends(msg, expectation): + expectation.update(failureMessage: failureMessage) + if let desc = failureMessage.userDescription { + failureMessage.userDescription = "\(msg)\(desc)" + } else { + failureMessage.userDescription = msg + } + case let .appends(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendMessage(msg) + case let .details(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendDetails(msg) + } + } +} + +extension FailureMessage { + internal func toExpectationMessage() -> ExpectationMessage { + let defaultMsg = FailureMessage() + if expected != defaultMsg.expected || _stringValueOverride != nil { + return .fail(stringValue) + } + + var msg: ExpectationMessage = .fail(userDescription ?? "") + if actualValue != "" && actualValue != nil { + msg = .expectedCustomValueTo(postfixMessage, actualValue ?? "") + } else if postfixMessage != defaultMsg.postfixMessage { + if actualValue == nil { + msg = .expectedTo(postfixMessage) + } else { + msg = .expectedActualValueTo(postfixMessage) + } + } + if postfixActual != defaultMsg.postfixActual { + msg = .appends(msg, postfixActual) + } + if let m = extendedMessage { + msg = .details(msg, m) + } + return msg + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +public class NMBExpectationMessage: NSObject { + private let msg: ExpectationMessage + + internal init(swift msg: ExpectationMessage) { + self.msg = msg + } + + public init(expectedTo message: String) { + self.msg = .expectedTo(message) + } + public init(expectedActualValueTo message: String) { + self.msg = .expectedActualValueTo(message) + } + + public init(expectedActualValueTo message: String, customActualValue actual: String) { + self.msg = .expectedCustomValueTo(message, actual) + } + + public init(fail message: String) { + self.msg = .fail(message) + } + + public init(prepend message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(appendedMessage message: String, child: NMBExpectationMessage) { + self.msg = .appends(child.msg, message) + } + + public init(prependedMessage message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(details message: String, child: NMBExpectationMessage) { + self.msg = .details(child.msg, message) + } + + public func appendedBeNilHint() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: msg.appendedBeNilHint()) + } + + public func toSwift() -> ExpectationMessage { return self.msg } +} + +extension ExpectationMessage { + func toObjectiveC() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..5a233fd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,99 @@ +import Foundation + +// Memoizes the given closure, only calling the passed +// closure once; even if repeat calls to the returned closure +internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { + var cache: T? + return ({ withoutCaching in + if withoutCaching || cache == nil { + cache = try closure() + } + return cache! + }) +} + +/// Expression represents the closure of the value inside expect(...). +/// Expressions are memoized by default. This makes them safe to call +/// evaluate() multiple times without causing a re-evaluation of the underlying +/// closure. +/// +/// @warning Since the closure can be any code, Objective-C code may choose +/// to raise an exception. Currently, Expression does not memoize +/// exception raising. +/// +/// This provides a common consumable API for matchers to utilize to allow +/// Nimble to change internals to how the captured closure is managed. +public struct Expression { + internal let _expression: (Bool) throws -> T? + internal let _withoutCaching: Bool + public let location: SourceLocation + public let isClosure: Bool + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. The expression is memoized. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { + self._expression = memoizedClosure(expression) + self.location = location + self._withoutCaching = false + self.isClosure = isClosure + } + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param withoutCaching Indicates if the struct should memoize the given + /// closure's result. Subsequent evaluate() calls will + /// not call the given closure if this is true. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { + self._expression = memoizedExpression + self.location = location + self._withoutCaching = withoutCaching + self.isClosure = isClosure + } + + /// Returns a new Expression from the given expression. Identical to a map() + /// on this type. This should be used only to typecast the Expression's + /// closure value. + /// + /// The returned expression will preserve location and isClosure. + /// + /// @param block The block that can cast the current Expression value to a + /// new type. + public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { + return Expression( + expression: ({ try block(self.evaluate()) }), + location: self.location, + isClosure: self.isClosure + ) + } + + public func evaluate() throws -> T? { + return try self._expression(_withoutCaching) + } + + public func withoutCaching() -> Expression { + return Expression( + memoizedExpression: self._expression, + location: location, + withoutCaching: true, + isClosure: isClosure + ) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..2bc57eb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,92 @@ +import Foundation + +/// Encapsulates the failure message that matchers can report to the end user. +/// +/// This is shared state between Nimble and matchers that mutate this value. +public class FailureMessage: NSObject { + public var expected: String = "expected" + public var actualValue: String? = "" // empty string -> use default; nil -> exclude + public var to: String = "to" + public var postfixMessage: String = "match" + public var postfixActual: String = "" + /// An optional message that will be appended as a new line and provides additional details + /// about the failure. This message will only be visible in the issue navigator / in logs but + /// not directly in the source editor since only a single line is presented there. + public var extendedMessage: String? + public var userDescription: String? + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + internal var hasOverriddenStringValue: Bool { + return _stringValueOverride != nil + } + + public override init() { + } + + public init(stringValue: String) { + _stringValueOverride = stringValue + } + + internal func stripNewlines(_ str: String) -> String { + let whitespaces = CharacterSet.whitespacesAndNewlines + return str + .components(separatedBy: "\n") + .map { line in line.trimmingCharacters(in: whitespaces) } + .joined(separator: "") + } + + internal func computeStringValue() -> String { + var value = "\(expected) \(to) \(postfixMessage)" + if let actualValue = actualValue { + value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" + } + value = stripNewlines(value) + + if let extendedMessage = extendedMessage { + value += "\n\(stripNewlines(extendedMessage))" + } + + if let userDescription = userDescription { + return "\(userDescription)\n\(value)" + } + + return value + } + + internal func appendMessage(_ msg: String) { + if hasOverriddenStringValue { + stringValue += "\(msg)" + } else if actualValue != nil { + postfixActual += msg + } else { + postfixMessage += msg + } + } + + internal func appendDetails(_ msg: String) { + if hasOverriddenStringValue { + if let desc = userDescription { + stringValue = "\(desc)\n\(stringValue)" + } + stringValue += "\n\(msg)" + } else { + if let desc = userDescription { + userDescription = desc + } + extendedMessage = msg + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 Jeff Hui. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..8affa62 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,121 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) throws -> Bool) -> Predicate + where U: Sequence, T == U.Iterator.Element { + let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in + return PredicateStatus(bool: try passFunc(try actualExpression.evaluate())) + } + return createPredicate(matcher) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate + 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(_ elementMatcher: M) -> Predicate + where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType { + return createPredicate(elementMatcher.predicate) +} + +public func allPass(_ elementPredicate: Predicate) -> Predicate + where S: Sequence { + return createPredicate(elementPredicate) +} + +private func createPredicate(_ elementMatcher: Predicate) -> Predicate + 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) + } + } + failure = failure.replacedExpectation({ expectation in + return .expectedTo(expectation.expectedMessage) + }) + return PredicateResult(status: .matches, message: failure) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate { + return NMBPredicate { actualExpression in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + var generator = NSFastEnumerationIterator(value) + while let obj = generator.next() { + if let nsObject = obj as? NSObject { + nsObjects.append(nsObject) + } else { + collectionIsUsable = false + break + } + } + } else { + collectionIsUsable = false + } + + if !collectionIsUsable { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + // swiftlint:disable:next line_length + fail: "allPass can only be used with types which implement NSFastEnumeration (NSArray, NSSet, ...), and whose elements subclass NSObject, got <\(actualValue?.description ?? "nil")>" + ) + ) + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in + if let predicate = matcher as? NMBPredicate { + return predicate.satisfies(({ try! expr.evaluate() }), location: expr.location).toSwift() + } else { + let failureMessage = FailureMessage() + let result = matcher.matches( + ({ try! expr.evaluate() }), + failureMessage: failureMessage, + location: expr.location + ) + let expectationMsg = failureMessage.toExpectationMessage() + return PredicateResult( + bool: result, + message: expectationMsg + ) + } + }) + return try! pred.satisfies(expr).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..3cba8b0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,236 @@ +import Foundation + +/// 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: TimeInterval = 1 + public static var PollInterval: TimeInterval = 0.01 +} + +private func async(style: ExpectationStyle, predicate: Predicate, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate { + return Predicate { actualExpression in + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).\(fnName)(...)" + var lastPredicateResult: PredicateResult? + let result = pollBlock( + pollInterval: poll, + timeoutInterval: timeout, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + lastPredicateResult = try predicate.satisfies(uncachedExpression) + return lastPredicateResult!.toBoolean(expectation: style) + } + switch result { + case .completed: return lastPredicateResult! + case .timedOut: return PredicateResult(status: .fail, message: lastPredicateResult!.message) + case let .errorThrown(error): + return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + case let .raisedException(exception): + return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) + case .blockedRunLoop: + // swiftlint:disable:next line_length + return PredicateResult(status: .fail, message: lastPredicateResult!.message.appended(message: " (timed out, but main thread was unresponsive).")) + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } +} + +// Deprecated +internal struct AsyncMatcherWrapper: Matcher + where U: Matcher, U.ValueType == T { + let fullMatcher: U + let timeoutInterval: TimeInterval + let pollInterval: TimeInterval + + init(fullMatcher: U, timeoutInterval: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval) { + self.fullMatcher = fullMatcher + self.timeoutInterval = timeoutInterval + self.pollInterval = pollInterval + } + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).toEventually(...)" + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + try self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: "expect(...).toEventuallyNot(...)") { + try self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventuallyNot(...).") + } + } +} + +private let toEventuallyRequiresClosureError = FailureMessage( + // swiftlint:disable:next line_length + stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function" +) + +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toMatch, + async(style: .toMatch, predicate: predicate, timeout: timeout, poll: pollInterval, fnName: "toEventually"), + to: "to eventually", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toNotMatch, + async( + style: .toNotMatch, + predicate: predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventuallyNot" + ), + to: "to eventually not", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + } +} + +// Deprecated +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionMatches( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + to: "to eventually", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionDoesNotMatch( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + toNot: "to eventually not", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..5674525 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,68 @@ +import Foundation + +private func matcherMessage(forType expectedType: T.Type) -> String { + return "be a kind of \(String(describing: expectedType))" +} +private func matcherMessage(forClass expectedClass: AnyClass) -> String { + return "be a kind of \(String(describing: expectedClass))" +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "") + return PredicateResult(status: .fail, message: message) + } + message = .expectedCustomValueTo( + "be a kind of \(String(describing: expectedType))", + "<\(String(describing: type(of: validInstance))) instance>" + ) + + return PredicateResult( + bool: validInstance is T, + message: message + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// 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 +public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + let status: PredicateStatus + + let instance = try actualExpression.evaluate() + if let validInstance = instance { + status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "<\(String(describing: type(of: validInstance))) instance>" + ) + } else { + status = .fail + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "" + ) + } + + return PredicateResult(status: status, message: message) + } +} + +extension NMBObjCMatcher { + @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAKindOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..70c5661 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,56 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. +public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedType))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + return PredicateResult( + status: .doesNotMatch, + message: .expectedActualValueTo(errorMessage) + ) + } + + let actualString = "<\(String(describing: type(of: validInstance))) instance>" + + return PredicateResult( + status: PredicateStatus(bool: type(of: validInstance) == expectedType), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAKindOf if you want to match against subclasses +public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedClass))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + let actualString: String + if let validInstance = instance { + actualString = "<\(String(describing: type(of: validInstance))) instance>" + } else { + actualString = "" + } + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let matches = instance != nil && instance!.isMember(of: expectedClass) + #else + let matches = instance != nil && type(of: instance!) == expectedClass + #endif + return PredicateResult( + status: PredicateStatus(bool: matches), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAnInstanceOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..dfb4e28 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,126 @@ +import Foundation + +public let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, + expectedValue: NMBDoubleConvertible, + delta: Double) + -> PredicateResult { + let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + return PredicateResult( + bool: actualValue != nil && + abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta, + message: .expectedCustomValueTo(errorMessage, "<\(stringify(actualValue))>") + ) +} + +/// 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: Double, within delta: Double = DefaultDelta) -> Predicate { + 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 { + return Predicate.define { actualExpression in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + 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) + return try! matcher.matches(expr, failureMessage: failureMessage) + } + + @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) + return try! matcher.doesNotMatch(expr, failureMessage: failureMessage) + } + + @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) + } +} +#endif + +public func beCloseTo(_ expectedValues: [Double], within delta: Double = DefaultDelta) -> Predicate<[Double]> { + let errorMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + return Predicate.simple(errorMessage) { actualExpression in + if let actual = try actualExpression.evaluate() { + if actual.count != expectedValues.count { + return .doesNotMatch + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return .doesNotMatch + } + } + return .matches + } + } + return .doesNotMatch + } +} + +// MARK: - Operators + +infix operator ≈ : ComparisonPrecedence + +public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +public 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 +// unexpectantly +precedencegroup PlusMinusOperatorPrecedence { + higherThan: BitwiseShiftPrecedence +} + +infix operator ± : PlusMinusOperatorPrecedence +public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) { + return (expected: lhs, delta: rhs) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..3cbc15d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,95 @@ +import Foundation + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return .fail + } + var generator = actualSeq!.makeIterator() + return PredicateStatus(bool: generator.next() == nil) + } +} + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0) + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For NSString instances, it is an empty string. +public func beEmpty() -> Predicate { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || actualString!.length == 0) + } +} + +// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, +// etc, since they conform to Sequence as well as NMBCollection. + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualDictionary = try actualExpression.evaluate() + return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.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 { + return Predicate.simple("be empty") { actualExpression in + let actualArray = try actualExpression.evaluate() + return PredicateStatus(bool: actualArray == nil || actualArray!.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 { + return Predicate.simple("be empty") { actualExpression in + let actual = try actualExpression.evaluate() + return PredicateStatus(bool: actual == nil || actual!.count == 0) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @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) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let actualValue = actualValue { + // swiftlint:disable:next line_length + let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + expectedActualValueTo: badTypeErrorMsg, + customActualValue: "\(String(describing: type(of: actualValue))) type" + ) + ) + } + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() + ) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..8717f97 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil + && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending + return matches + }.requireNonNil +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..55d8e7b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -0,0 +1,44 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if let actual = actualValue, let expected = expectedValue { + return actual >= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..ad19def --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -0,0 +1,46 @@ +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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if os(Linux) + let actual = try actualExpression.evaluate() as? AnyObject + #else + let actual = try actualExpression.evaluate() as AnyObject? + #endif + failureMessage.actualValue = "\(identityAsString(actual))" + failureMessage.postfixMessage = "be identical to \(identityAsString(expected))" + #if os(Linux) + return actual === (expected as? AnyObject) && actual !== nil + #else + return actual === (expected as AnyObject?) && actual !== nil + #endif + }.requireNonNil +} + +public func === (lhs: Expectation, rhs: Any?) { + lhs.to(beIdenticalTo(rhs)) +} +public func !== (lhs: Expectation, rhs: Any?) { + lhs.toNot(beIdenticalTo(rhs)) +} + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +/// +/// Alias for "beIdenticalTo". +public func be(_ expected: Any?) -> Predicate { + return beIdenticalTo(expected) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let aExpr = actualExpression.cast { $0 as Any? } + return try! beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..8047efd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual < expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..f9e9f4e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual <= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + return actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedDescending + }.requireNonNil +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..2b18b4c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,167 @@ +import Foundation + +extension Int8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int8Value + } +} + +extension UInt8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint8Value + } +} + +extension Int16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int16Value + } +} + +extension UInt16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint16Value + } +} + +extension Int32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int32Value + } +} + +extension UInt32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint32Value + } +} + +extension Int64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int64Value + } +} + +extension UInt64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint64Value + } +} + +extension Float: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).floatValue + } +} + +extension Double: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).doubleValue + } +} + +extension Int: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).intValue + } +} + +extension UInt: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uintValue + } +} + +internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { + return Predicate { actualExpression in + let result = try matcher.satisfies(actualExpression) + return PredicateResult(status: result.status, message: message) + }.requireNonNil +} + +// MARK: beTrue() / beFalse() + +/// A Nimble matcher that succeeds when the actual value is exactly true. +/// This matcher will not match against nils. +public func beTrue() -> Predicate { + return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> Predicate { + return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> Predicate { + return Predicate.simpleNilable("be truthy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == true) + } + + return PredicateStatus(bool: actualValue == (true as T)) + } + return PredicateStatus(bool: actualValue != nil) + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> Predicate { + return Predicate.simpleNilable("be falsy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == false) + } + + return PredicateStatus(bool: actualValue == (false as T)) + } + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beTruthyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTruthy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalsyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalsy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beTrueMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTrue().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalseMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalse().matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..a22e0f4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,19 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> Predicate { + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..f5bf22a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift @@ -0,0 +1,18 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is Void. +public func beVoid() -> Predicate<()> { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be void" + let actualValue: ()? = try actualExpression.evaluate() + return actualValue != nil + } +} + +public func == (lhs: Expectation<()>, rhs: ()) { + lhs.to(beVoid()) +} + +public func != (lhs: Expectation<()>, rhs: ()) { + lhs.toNot(beVoid()) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..c2ab568 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,60 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's first element +/// is equal to the expected value. +public func beginWith(_ startingElement: T) -> Predicate + where S.Iterator.Element == T { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> Predicate { + return Predicate.simple("begin with <\(startingElement)>") { actualExpression in + guard let collection = try actualExpression.evaluate() else { return .fail } + guard collection.count > 0 else { return .doesNotMatch } + #if os(Linux) + guard let collectionValue = collection.object(at: 0) as? NSObject else { + return .fail + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return PredicateStatus(bool: collectionValue.isEqual(startingElement)) + } +} + +/// A Nimble matcher that succeeds when the actual string contains expected substring +/// where the expected substring's location is zero. +public func beginWith(_ startingSubstring: String) -> Predicate { + return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return PredicateStatus(bool: range != nil && range!.lowerBound == actual.startIndex) + } + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! beginWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..f1afb72 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,95 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> Predicate + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + if let actual = try actualExpression.evaluate() { + return items.all { + return actual.contains($0) + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { + let range = actual.range(of: $0) + return range != nil && !range!.isEmpty + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { actual.range(of: $0.description).length != 0 } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> Predicate { + return contain(items) +} + +public func contain(_ items: [Any?]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + guard let actual = try actualExpression.evaluate() else { return false } + return items.all { item in + return item != nil && actual.contains(item!) + } + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + if let value = actualValue as? NMBContainer { + let expr = Expression(expression: ({ value as NMBContainer }), location: location) + + // A straightforward cast on the array causes this to crash, so we have to cast the individual items + let expectedOptionals: [Any?] = expected.map({ $0 as Any? }) + return try! contain(expectedOptionals).matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! contain(expected as! [String]).matches(expr, failureMessage: failureMessage) + } else if actualValue != nil { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)" + } else { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..ae0d854 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,60 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T { + + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.actualValue = nil + + if predicateDescription == "" { + failureMessage.postfixMessage = "find object in collection that satisfies predicate" + } else { + failureMessage.postfixMessage = "find object in collection \(predicateDescription)" + } + + if let sequence = try actualExpression.evaluate() { + for object in sequence { + if predicate(object) { + return true + } + } + + return false + } + + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + extension NMBObjCMatcher { + @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let value = try! actualExpression.evaluate() + guard let enumeration = value as? NSFastEnumeration else { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + var iterator = NSFastEnumerationIterator(enumeration) + while let item = iterator.next() { + guard let object = item as? NSObject else { + continue + } + + if predicate(object) { + return true + } + } + + failureMessage.actualValue = nil + failureMessage.postfixMessage = "" + failureMessage.to = "to find object in collection that satisfies predicate" + return false + } + } + } +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..a6f9f91 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift @@ -0,0 +1,72 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's last element +/// is equal to the expected value. +public func endWith(_ endingElement: T) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + + 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) + + return lastItem == endingElement + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + guard let collection = try actualExpression.evaluate() else { return false } + guard collection.count > 0 else { return false } + #if os(Linux) + guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: collection.count - 1) as AnyObject + #endif + + return collectionValue.isEqual(endingElement) + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring +/// where the expected substring's location is the actual string's length minus the +/// expected substring's length. +public func endWith(_ endingSubstring: String) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingSubstring)>" + if let collection = try actualExpression.evaluate() { + return collection.hasSuffix(endingSubstring) + } + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! endWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! endWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..9467154 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,220 @@ +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. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(status: PredicateStatus(bool: matches), message: msg) + } +} + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: [T: C]?) -> Predicate<[T: C]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult( + status: PredicateStatus(bool: expectedValue! == actualValue!), + message: msg + ) + } +} + +/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection. +/// Items must implement the Equatable protocol. +public func equal(_ expectedValue: [T]?) -> Predicate<[T]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult( + status: .fail, + message: msg + ) + } + return PredicateResult( + bool: expectedValue! == actualValue!, + message: msg + ) + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + if let actualValue = try actualExpression.evaluate() { + let doesNotMatch = PredicateResult( + status: .doesNotMatch, + message: msg + ) + + if expectedValue.count != actualValue.count { + return doesNotMatch + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return doesNotMatch + } else if item != nil && otherItem == nil { + return doesNotMatch + } else if item! != otherItem! { + return doesNotMatch + } + } + + return PredicateResult( + status: .matches, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { stringify($0) }) +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { + if let set = $0 { + return stringify(Array(set).sorted { $0 < $1 }) + } else { + return "nil" + } + }) +} + +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { + return Predicate { actualExpression in + var errorMessage: ExpectationMessage = + .expectedActualValueTo("equal <\(stringify(expectedValue))>") + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + errorMessage = .expectedCustomValueTo( + "equal <\(stringify(expectedValue))>", + "<\(stringify(actualValue))>" + ) + + if expectedValue == actualValue { + return PredicateResult( + status: .matches, + message: errorMessage + ) + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>") + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") + } + return PredicateResult( + status: .doesNotMatch, + message: errorMessage + ) + } + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } else { + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } + } +} + +public func ==(lhs: Expectation, rhs: T?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation, rhs: T?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.toNot(equal(rhs)) +} + +public func == (lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func != (lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.toNot(equal(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! equal(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..93335a8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,59 @@ +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. +// The representation of the collection content is provided in a new line as an `extendedMessage`. + +/// A Nimble matcher that succeeds when the actual Collection's count equals +/// the expected value +public func haveCount(_ expectedValue: T.IndexDistance) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage 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) + return try! haveCount(expected.intValue).matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable" + failureMessage.actualValue = "\(String(describing: type(of: actualValue)))" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..1e5762f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift @@ -0,0 +1,30 @@ +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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "match <\(stringify(expectedValue))>" + + if let actual = try actualExpression.evaluate() { + if let regexp = expectedValue { + return actual.range(of: regexp, options: .regularExpression) != nil + } + } + + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +extension NMBObjCMatcher { + @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.cast { $0 as? String } + return try! match(expected.description).matches(actual, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..9c86fb7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,58 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + errorType: errorType + ) + var matches = false + if actualError as? T != nil { + matches = true + } + return matches + }.requireNonNil +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..abcafa9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,85 @@ +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil +/// values are received in an expectation. +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct MatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try matcher(actualExpression, failureMessage) + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try !matcher(actualExpression, failureMessage) + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} + +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// Unlike MatcherFunc, this will always fail if an expectation contains nil. +/// This applies regardless of using to() or toNot(). +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct NonNilMatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try !matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return true + } + return false + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..82f3cf0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,154 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +@available(*, deprecated, message: "Use Predicate instead") +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +extension Matcher { + var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } + + var toClosure: (Expression, FailureMessage, Bool) throws -> Bool { + return ({ expr, msg, expectedResult in + if expectedResult { + return try self.matches(expr, failureMessage: msg) + } else { + return try self.doesNotMatch(expr, failureMessage: msg) + } + }) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +/// Objective-C interface to the Swift variant of Matcher. +@objc public protocol NMBMatcher { + func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool + func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool +} +#endif + +/// Protocol for types that support contain() matcher. +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a +//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet +#endif + +extension NSArray: NMBContainer {} +extension NSSet: NMBContainer {} + +/// Protocol for types that support only beEmpty(), haveCount() matchers +public protocol NMBCollection { + var count: Int { get } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable: NMBCollection {} +#endif + +extension NSSet: NMBCollection {} +extension NSIndexSet: NMBCollection {} +extension NSDictionary: NMBCollection {} + +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} + +extension NSArray: NMBOrderedCollection {} + +public protocol NMBDoubleConvertible { + var doubleValue: CDouble { get } +} + +extension Double: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self + } +} + +extension Float: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension CGFloat: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension NSNumber: NMBDoubleConvertible { +} + +private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.locale = Locale(identifier: "en_US_POSIX") + + return formatter +}() + +extension Date: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension NSDate: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension Date: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: self) + } +} + +extension NSDate: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) + } +} + +/// 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 os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@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 { + return compare(otherObject as! NSNumber) + } +} +extension NSString: NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! String) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..ee886f1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,96 @@ +import Foundation + +// A workaround to SR-6419. +extension NotificationCenter { +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + #if swift(>=4.0) + #if swift(>=4.0.2) + #else + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #elseif swift(>=3.2) + #if swift(>=3.2.2) + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif +#endif +} + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + // swiftlint:disable:next line_length + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil, using: { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + }) + } + + deinit { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + if let token = self.token { + self.notificationCenter.removeObserver(token) + } + #else + if let token = self.token as? AnyObject { + self.notificationCenter.removeObserver(token) + } + #endif + } +} + +private let mainThread = pthread_self() + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = .default) + -> Predicate + where T: Matcher, T.ValueType == [Notification] +{ + _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + collector.startObserving() + var once: Bool = false + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage 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 match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) + if collector.observedNotifications.isEmpty { + failureMessage.actualValue = "no notifications" + } else { + failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" + } + return match + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift new file mode 100644 index 0000000..d32b0e2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift @@ -0,0 +1,348 @@ +// New Matcher API +// +import Foundation + +/// A Predicate is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate +/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble +/// matcher API. +/// +/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, +/// predicates are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +public struct Predicate { + fileprivate var matcher: (Expression) throws -> PredicateResult + + /// Constructs a predicate that knows how take a given value + public init(_ matcher: @escaping (Expression) throws -> PredicateResult) { + self.matcher = matcher + } + + /// Uses a predicate on a given value to see if it passes the predicate. + /// + /// @param expression The value to run the predicate's logic against + /// @returns A predicate result indicate passing or failing and an associated error message. + public func satisfies(_ expression: Expression) throws -> PredicateResult { + return try matcher(expression) + } +} + +/// Provides convenience helpers to defining predicates +extension Predicate { + /// Like Predicate() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (Expression) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual) + }.requireNonNil + } + + /// 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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + }.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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + } + } +} + +extension Predicate { + /// Provides a simple predicate definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the predicate's actual value cannot pass with `nil` given. + public static func simple(_ msg: String, matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + }.requireNonNil + } + + /// Provides a simple predicate definition that provides no control over the predefined + /// 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) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + } + } +} + +// The Expectation style intended for comparison to a PredicateStatus. +public enum ExpectationStyle { + case toMatch, toNotMatch +} + +/// The value that a Predicates return to describe if the given (actual) value matches the +/// predicate. +public struct PredicateResult { + /// Status indicates if the predicate matches, does not match, or fails. + public var status: PredicateStatus + /// The error message that can be displayed if it does not match + public var message: ExpectationMessage + + /// Constructs a new PredicateResult with a given status and error message + public init(status: PredicateStatus, message: ExpectationMessage) { + self.status = status + self.message = message + } + + /// Shorthand to PredicateResult(status: PredicateStatus(bool: bool), message: message) + public init(bool: Bool, message: ExpectationMessage) { + self.status = PredicateStatus(bool: bool) + self.message = message + } + + /// Converts the result to a boolean based on what the expectation intended + public func toBoolean(expectation style: ExpectationStyle) -> Bool { + return status.toBoolean(expectation: style) + } +} + +/// PredicateStatus is a trinary that indicates if a Predicate matches a given value or not +public enum PredicateStatus { + /// Matches indicates if the predicate / matcher passes with the given value + /// + /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. + case matches + /// DoesNotMatch indicates if the predicate / matcher fails with the given value, but *would* + /// succeed if the expectation was inverted. + /// + /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. + case doesNotMatch + /// Fail indicates the predicate will never satisfy with the given value in any case. + /// A perfect example is that most matchers fail whenever given `nil`. + /// + /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. + /// Note: Predicate's `requireNonNil` property will also provide this feature mostly for free. + /// Your predicate will still need to guard against nils, but error messaging will be + /// handled for you. + case fail + + /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). + public init(bool matches: Bool) { + if matches { + self = .matches + } else { + self = .doesNotMatch + } + } + + private func shouldMatch() -> Bool { + switch self { + case .matches: return true + case .doesNotMatch, .fail: return false + } + } + + private func shouldNotMatch() -> Bool { + switch self { + case .doesNotMatch: return true + case .matches, .fail: return false + } + } + + /// Converts the PredicateStatus result to a boolean based on what the expectation intended + internal func toBoolean(expectation style: ExpectationStyle) -> Bool { + if style == .toMatch { + return shouldMatch() + } else { + return shouldNotMatch() + } + } +} + +// Backwards compatibility until Old Matcher API removal +extension Predicate: Matcher { + /// Compatibility layer for old Matcher API, deprecated + public static func fromDeprecatedFullClosure(_ matcher: @escaping (Expression, FailureMessage, Bool) throws -> Bool) -> Predicate { + return Predicate { actual in + let failureMessage = FailureMessage() + let result = try matcher(actual, failureMessage, true) + return PredicateResult( + status: PredicateStatus(bool: result), + message: failureMessage.toExpectationMessage() + ) + } + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Emulates the MatcherFunc API + public static func fromDeprecatedClosure(_ matcher: @escaping (Expression, 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() + ) + } + + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Same as calling .predicate on a MatcherFunc or NonNilMatcherFunc type. + public static func fromDeprecatedMatcher(_ matcher: M) -> Predicate where M: Matcher, M.ValueType == T { + return self.fromDeprecatedFullClosure(matcher.toClosure) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toMatch) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toNotMatch) + } +} + +extension Predicate { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (Expression, PredicateResult) throws -> PredicateResult) -> Predicate { + return Predicate { actual -> PredicateResult in + let result = try self.satisfies(actual) + return try f(actual, result) + } + } + + /// Returns a new Predicate based on the current one that always fails if nil is given as + /// the actual value. + /// + /// This replaces `NonNilMatcherFunc`. + public var requireNonNil: Predicate { + return after { actual, result in + if try actual.evaluate() == nil { + return PredicateResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public typealias PredicateBlock = (_ actualExpression: Expression) -> NMBPredicateResult + +public class NMBPredicate: NSObject { + private let predicate: PredicateBlock + + public init(predicate: @escaping PredicateBlock) { + self.predicate = predicate + } + + func satisfies(_ expression: @escaping () -> NSObject!, location: SourceLocation) -> NMBPredicateResult { + let expr = Expression(expression: expression, location: location) + return self.predicate(expr) + } +} + +extension NMBPredicate: NMBMatcher { + public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toMatch) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toNotMatch) + } +} + +final public class NMBPredicateResult: NSObject { + public var status: NMBPredicateStatus + public var message: NMBExpectationMessage + + public init(status: NMBPredicateStatus, message: NMBExpectationMessage) { + self.status = status + self.message = message + } + + public init(bool success: Bool, message: NMBExpectationMessage) { + self.status = NMBPredicateStatus.from(bool: success) + self.message = message + } + + public func toSwift() -> PredicateResult { + return PredicateResult(status: status.toSwift(), + message: message.toSwift()) + } +} + +extension PredicateResult { + public func toObjectiveC() -> NMBPredicateResult { + return NMBPredicateResult(status: status.toObjectiveC(), message: message.toObjectiveC()) + } +} + +final public class NMBPredicateStatus: NSObject { + private let status: Int + private init(status: Int) { + self.status = status + } + + public static let matches: NMBPredicateStatus = NMBPredicateStatus(status: 0) + public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1) + public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2) + + public override var hashValue: Int { return self.status.hashValue } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherPredicate = object as? NMBPredicateStatus else { + return false + } + return self.status == otherPredicate.status + } + + public static func from(status: PredicateStatus) -> NMBPredicateStatus { + switch status { + case .matches: return self.matches + case .doesNotMatch: return self.doesNotMatch + case .fail: return self.fail + } + } + + public static func from(bool success: Bool) -> NMBPredicateStatus { + return self.from(status: PredicateStatus(bool: success)) + } + + public func toSwift() -> PredicateStatus { + switch status { + case NMBPredicateStatus.matches.status: return .matches + case NMBPredicateStatus.doesNotMatch.status: return .doesNotMatch + case NMBPredicateStatus.fail.status: return .fail + default: + internalError("Unhandle status for NMBPredicateStatus") + } + } +} + +extension PredicateStatus { + public func toObjectiveC() -> NMBPredicateStatus { + return NMBPredicateStatus.from(status: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..60553bd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,198 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +/// 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( + named: String? = nil, + reason: String? = nil, + userInfo: NSDictionary? = nil, + closure: ((NSException) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var exception: NSException? + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + _ = try! actualExpression.evaluate() + return + } + + setFailureMessageForException( + failureMessage, + exception: exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + return exceptionMatchesNonNilFieldsOrClosure( + exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + } +} + +// swiftlint:disable:next function_parameter_count +internal func setFailureMessageForException( + _ failureMessage: FailureMessage, + exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) { + failureMessage.postfixMessage = "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 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" + } +} + +internal func exceptionMatchesNonNilFieldsOrClosure( + _ exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) -> Bool { + var matches = false + + if let exception = exception { + matches = true + + if let named = named, exception.name.rawValue != named { + matches = false + } + if reason != nil && exception.reason != reason { + matches = false + } + if let userInfo = userInfo, let exceptionUserInfo = exception.userInfo, + (exceptionUserInfo as NSDictionary) != userInfo { + matches = false + } + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(exception) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} + +public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher { + internal var _name: String? + internal var _reason: String? + internal var _userInfo: NSDictionary? + internal var _block: ((NSException) -> Void)? + + internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) { + _name = name + _reason = reason + _userInfo = userInfo + _block = block + } + + @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) + + return try! raiseException( + named: _name, + reason: _reason, + userInfo: _userInfo, + closure: _block + ).matches(expr, failureMessage: failureMessage) + } + + @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( + 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 + ) + }) + } +} + +extension NMBObjCMatcher { + @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift new file mode 100644 index 0000000..6c63a15 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift @@ -0,0 +1,101 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAllOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAllOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = true + for matcher in matchers { + if try matcher.doesNotMatch(actualExpression, failureMessage: failureMessage) { + matches = false + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match all of: " + postfixMessages.componentsJoined(by: ", and ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = true + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toNotMatch) { + matches = false + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match all of: " + postfixMessages.joined(separator: ", and "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match all of: " + postfixMessages.joined(separator: ", and ") + ) + } + + return PredicateResult( + bool: matches, + message: msg + ) + }.requireNonNil +} + +public func && (left: Predicate, right: Predicate) -> Predicate { + return satisfyAllOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAllOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..d02a0ff --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,109 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAnyOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = false + for matcher in matchers { + if try matcher.matches(actualExpression, failureMessage: failureMessage) { + matches = true + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match one of: " + postfixMessages.componentsJoined(by: ", or ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = false + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toMatch) { + matches = true + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match one of: " + postfixMessages.joined(separator: ", or "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match one of: " + postfixMessages.joined(separator: ", or ") + ) + } + + return PredicateResult( + status: PredicateStatus(bool: matches), + message: msg + ) + }.requireNonNil +} + +public func || (left: Predicate, right: Predicate) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAnyOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..a530c60 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,56 @@ +import Foundation + +public func throwAssertion() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if arch(x86_64) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + failureMessage.postfixMessage = "throw an assertion" + failureMessage.actualValue = nil + + var succeeded = true + + let caughtException: BadInstructionException? = catchBadInstruction { + #if os(tvOS) + if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { + print() + print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + + "fatal error while using throwAssertion(), please disable 'Debug Executable' " + + "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + + "'Debug Executable'. If you've already done that, suppress this warning " + + "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + + "This is required because the standard methods of catching assertions " + + "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + + "debugger uses is the fallback method for tvOS." + ) + print() + NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true + } + #endif + do { + try actualExpression.evaluate() + } catch let error { + succeeded = false + failureMessage.postfixMessage += "; threw error instead <\(error)>" + } + } + + if !succeeded { + return false + } + + if caughtException == nil { + return false + } + + return true + #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. Mac, iPhone 5s or later simulators). You can silence this error " + + "by placing the test case inside an #if arch(x86_64) or (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) conditional statement") + // swiftlint:disable:previous line_length + #endif + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..872ca5c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,258 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + failureMessage.postfixMessage = "throw any error" + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } + return actualError != nil + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError( + errorType: T.Type, + closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: nil, + errorType: errorType, + closure: closure + ) + var matches = false + if let actualError = actualError { + matches = true + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } else { + matches = (actualError is T) + // The closure expects another ErrorProtocol as argument, so this + // is _supposed_ to fail, so that it becomes more obvious. + if let closure = closure { + let assertions = gatherExpectations { + if let actual = actualError as? T { + closure(actual) + } + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + } + + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// 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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// values of the existential type `Error` in the closure. +/// +/// The closure only gets called when an error was thrown. +public func throwError(closure: @escaping ((T) -> Void)) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError as? T { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift new file mode 100644 index 0000000..01369bb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift @@ -0,0 +1,37 @@ +/** + Used by the `toSucceed` matcher. + + This is the return type for the closure. + */ +public enum ToSucceedResult { + case succeeded + case failed(reason: String) +} + +/** + A Nimble matcher that takes in a closure for validation. + + Return `.succeeded` when the validation succeeds. + Return `.failed` with a failure reason when the validation fails. + */ +public func succeed() -> Predicate<() -> ToSucceedResult> { + return Predicate.define { actualExpression in + let optActual = try actualExpression.evaluate() + guard let actual = optActual else { + return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) + } + + switch actual() { + case .succeeded: + return PredicateResult( + bool: true, + message: .expectedCustomValueTo("succeed", "") + ) + case .failed(let reason): + return PredicateResult( + bool: false, + message: .expectedCustomValueTo("succeed", " because <\(reason)>") + ) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..2bbc693 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,13 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#if TARGET_OS_TV + #import "CwlPreconditionTesting_POSIX.h" +#else + #import "CwlPreconditionTesting.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..c77a8fc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,377 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + import CDispatch +#endif + +private let timeoutLeeway = DispatchTimeInterval.milliseconds(1) +private let pollLeeway = DispatchTimeInterval.milliseconds(1) + +/// Stores debugging information about callers +internal struct WaitingInfo: CustomStringConvertible { + let name: String + let file: FileString + let lineNumber: UInt + + var description: String { + return "\(name) at \(file):\(lineNumber)" + } +} + +internal protocol WaitLock { + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) + func releaseWaitingLock() + func isWaitingLocked() -> Bool +} + +internal class AssertionWaitLock: WaitLock { + private var currentWaiter: WaitingInfo? + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let isMainThread = Thread.isMainThread + #else + let isMainThread = _CFIsMainThread() + #endif + nimblePrecondition( + isMainThread, + "InvalidNimbleAPIUsage", + "\(fnName) can only run on the main thread." + ) + nimblePrecondition( + currentWaiter == nil, + "InvalidNimbleAPIUsage", + "Nested async expectations are not allowed to avoid creating flaky tests.\n\n" + + "The call to\n\t\(info)\n" + + "triggered this exception because\n\t\(currentWaiter!)\n" + + "is currently managing the main run loop." + ) + currentWaiter = info + } + + func isWaitingLocked() -> Bool { + return currentWaiter != nil + } + + func releaseWaitingLock() { + currentWaiter = nil + } +} + +internal enum AwaitResult { + /// Incomplete indicates None (aka - this value hasn't been fulfilled yet) + case incomplete + /// TimedOut indicates the result reached its defined timeout limit before returning + case timedOut + /// BlockedRunLoop indicates the main runloop is too busy processing other blocks to trigger + /// the timeout code. + /// + /// This may also mean the async code waiting upon may have never actually ran within the + /// required time because other timers & sources are running on the main run loop. + case blockedRunLoop + /// The async block successfully executed and returned a given result + case completed(T) + /// When a Swift Error is thrown + case errorThrown(Error) + /// When an Objective-C Exception is raised + case raisedException(NSException) + + func isIncomplete() -> Bool { + switch self { + case .incomplete: return true + default: return false + } + } + + func isCompleted() -> Bool { + switch self { + case .completed: return true + default: return false + } + } +} + +/// Holds the resulting value from an asynchronous expectation. +/// This class is thread-safe at receiving an "response" to this promise. +internal class AwaitPromise { + private(set) internal var asyncResult: AwaitResult = .incomplete + private var signal: DispatchSemaphore + + init() { + signal = DispatchSemaphore(value: 1) + } + + deinit { + signal.signal() + } + + /// Resolves the promise with the given result if it has not been resolved. Repeated calls to + /// this method will resolve in a no-op. + /// + /// @returns a Bool that indicates if the async result was accepted or rejected because another + /// value was received first. + func resolveResult(_ result: AwaitResult) -> Bool { + if signal.wait(timeout: .now()) == .success { + self.asyncResult = result + return true + } else { + return false + } + } +} + +internal struct AwaitTrigger { + let timeoutSource: DispatchSourceTimer + let actionSource: DispatchSourceTimer? + let start: () throws -> Void +} + +/// Factory for building fully configured AwaitPromises and waiting for their results. +/// +/// This factory stores all the state for an async expectation so that Await doesn't +/// doesn't have to manage it. +internal class AwaitPromiseBuilder { + let awaiter: Awaiter + let waitLock: WaitLock + let trigger: AwaitTrigger + let promise: AwaitPromise + + internal init( + awaiter: Awaiter, + waitLock: WaitLock, + promise: AwaitPromise, + trigger: AwaitTrigger) { + self.awaiter = awaiter + self.waitLock = waitLock + self.promise = promise + self.trigger = trigger + } + + func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + // = Discussion = + // + // There's a lot of technical decisions here that is useful to elaborate on. This is + // definitely more lower-level than the previous NSRunLoop based implementation. + // + // + // Why Dispatch Source? + // + // + // We're using a dispatch source to have better control of the run loop behavior. + // A timer source gives us deferred-timing control without having to rely as much on + // a run loop's traditional dispatching machinery (eg - NSTimers, DefaultRunLoopMode, etc.) + // which is ripe for getting corrupted by application code. + // + // And unlike dispatch_async(), we can control how likely our code gets prioritized to + // executed (see leeway parameter) + DISPATCH_TIMER_STRICT. + // + // This timer is assumed to run on the HIGH priority queue to ensure it maintains the + // highest priority over normal application / test code when possible. + // + // + // Run Loop Management + // + // In order to properly interrupt the waiting behavior performed by this factory class, + // this timer stops the main run loop to tell the waiter code that the result should be + // checked. + // + // In addition, stopping the run loop is used to halt code executed on the main run loop. + #if swift(>=4.0) + trigger.timeoutSource.schedule( + deadline: DispatchTime.now() + timeoutInterval, + repeating: .never, + leeway: timeoutLeeway + ) + #else + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway + ) + #endif + trigger.timeoutSource.setEventHandler { + guard self.promise.asyncResult.isIncomplete() else { return } + let timedOutSem = DispatchSemaphore(value: 0) + let semTimedOutOrBlocked = DispatchSemaphore(value: 0) + semTimedOutOrBlocked.signal() + let runLoop = CFRunLoopGetMain() + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + let now = DispatchTime.now() + forcefullyAbortTimeout + let didNotTimeOut = timedOutSem.wait(timeout: now) != .success + let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success + if didNotTimeOut && timeoutWasNotTriggered { + if self.promise.resolveResult(.blockedRunLoop) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + return self + } + + /// Blocks for an asynchronous result. + /// + /// @discussion + /// This function must be executed on the main thread and cannot be nested. This is because + /// this function (and it's related methods) coordinate through the main run loop. Tampering + /// with the run loop can cause undesirable behavior. + /// + /// This method will return an AwaitResult in the following cases: + /// + /// - The main run loop is blocked by other operations and the async expectation cannot be + /// be stopped. + /// - The async expectation timed out + /// - The async expectation succeeded + /// - The async expectation raised an unexpected exception (objc) + /// - The async expectation raised an unexpected error (swift) + /// + /// The returned AwaitResult will NEVER be .incomplete. + func wait(_ fnName: String = #function, file: FileString = #file, line: UInt = #line) -> AwaitResult { + waitLock.acquireWaitingLock( + fnName, + file: file, + line: line) + + let capture = NMBExceptionCapture(handler: ({ exception in + _ = self.promise.resolveResult(.raisedException(exception)) + }), finally: ({ + self.waitLock.releaseWaitingLock() + })) + capture.tryBlock { + do { + try self.trigger.start() + } catch let error { + _ = self.promise.resolveResult(.errorThrown(error)) + } + self.trigger.timeoutSource.resume() + while self.promise.asyncResult.isIncomplete() { + // Stopping the run loop does not work unless we run only 1 mode + _ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture) + } + + self.trigger.timeoutSource.cancel() + if let asyncSource = self.trigger.actionSource { + asyncSource.cancel() + } + } + + return promise.asyncResult + } +} + +internal class Awaiter { + let waitLock: WaitLock + let timeoutQueue: DispatchQueue + let asyncQueue: DispatchQueue + + internal init( + waitLock: WaitLock, + asyncQueue: DispatchQueue, + timeoutQueue: DispatchQueue) { + self.waitLock = waitLock + self.asyncQueue = asyncQueue + self.timeoutQueue = timeoutQueue + } + + private func createTimerSource(_ queue: DispatchQueue) -> DispatchSourceTimer { + return DispatchSource.makeTimerSource(flags: .strict, queue: queue) + } + + func performBlock( + file: FileString, + line: UInt, + _ closure: @escaping (@escaping (T) -> Void) throws -> Void + ) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + var completionCount = 0 + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) { + try closure { + completionCount += 1 + if completionCount < 2 { + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } else { + fail("waitUntil(..) expects its completion closure to be only called once", + file: file, line: line) + } + } + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } + + func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + 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))) + #if swift(>=4.0) + asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway) + #else + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + #endif + asyncSource.setEventHandler { + do { + if let result = try closure() { + if promise.resolveResult(.completed(result)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } catch let error { + if promise.resolveResult(.errorThrown(error)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } + asyncSource.resume() + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } +} + +internal func pollBlock( + pollInterval: TimeInterval, + timeoutInterval: TimeInterval, + file: FileString, + line: UInt, + fnName: String = #function, + expression: @escaping () throws -> Bool) -> AwaitResult { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let result = awaiter.poll(pollInterval) { () throws -> Bool? in + if try expression() { + return true + } + return nil + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..074cb20 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,59 @@ +import Foundation + +// Generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + postfixMessageVerb: String = "throw", + actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) { + failureMessage.postfixMessage = "\(postfixMessageVerb) error" + + if let error = error { + failureMessage.postfixMessage += " <\(error)>" + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } + if error == nil && errorType == nil && closure == nil { + failureMessage.postfixMessage = "\(postfixMessageVerb) any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool { + return actualError._domain == expectedError._domain + && actualError._code == expectedError._code +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift @@ -0,0 +1,12 @@ +import Foundation + +extension Sequence { + internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool { + for item in self { + if !fn(item) { + return false + } + } + return true + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift @@ -0,0 +1,31 @@ +import Foundation + +// Ideally we would always use `StaticString` as the type for tracking the file name +// that expectations originate from, for consistency with `assert` etc. from the +// stdlib, and because recent versions of the XCTest overlay require `StaticString` +// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we +// have to use `String` instead because StaticString can't be generated from Objective-C +#if SWIFT_PACKAGE +public typealias FileString = StaticString +#else +public typealias FileString = String +#endif + +public final class SourceLocation: NSObject { + public let file: FileString + public let line: UInt + + override init() { + file = "Unknown File" + line = 0 + } + + init(file: FileString, line: UInt) { + self.file = file + self.line = line + } + + override public var description: String { + return "\(file):\(line)" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..cd6de20 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift @@ -0,0 +1,212 @@ +import Foundation + +internal func identityAsString(_ value: Any?) -> String { + let anyObject: AnyObject? +#if os(Linux) + anyObject = value as? AnyObject +#else + anyObject = value as AnyObject? +#endif + if let value = anyObject { + return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description + } else { + return "nil" + } +} + +internal func arrayAsString(_ items: [T], joiner: String = ", ") -> String { + return items.reduce("") { accum, item in + let prefix = (accum.isEmpty ? "" : joiner) + return accum + prefix + "\(stringify(item))" + } +} + +/// A type with a customized test output text representation. +/// +/// This textual representation is produced when values will be +/// printed in test runs, and may be useful when producing +/// error messages in custom matchers. +/// +/// - SeeAlso: `CustomDebugStringConvertible` +public protocol TestOutputStringConvertible { + var testDescription: String { get } +} + +extension Double: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension Float: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +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 { + case 1: + return NSString(format: "%0.1f", self.doubleValue).description + case 2: + return NSString(format: "%0.2f", self.doubleValue).description + case 3: + return NSString(format: "%0.3f", self.doubleValue).description + default: + return NSString(format: "%0.4f", self.doubleValue).description + } + } + return self.description + } +} + +extension Array: TestOutputStringConvertible { + public var testDescription: String { + let list = self.map(Nimble.stringify).joined(separator: ", ") + return "[\(list)]" + } +} + +extension AnySequence: TestOutputStringConvertible { + public var testDescription: String { + let generator = self.makeIterator() + var strings = [String]() + var value: AnySequence.Iterator.Element? + + repeat { + value = generator.next() + if let value = value { + strings.append(stringify(value)) + } + } while value != nil + + let list = strings.joined(separator: ", ") + return "[\(list)]" + } +} + +extension NSArray: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension NSIndexSet: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension String: TestOutputStringConvertible { + public var testDescription: String { + return self + } +} + +extension Data: TestOutputStringConvertible { + public var testDescription: String { + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16) + return "Data" + #else + return "Data" + #endif + } +} + +/// +/// Returns a string appropriate for displaying in test output +/// from the provided value. +/// +/// - parameter value: A value that will show up in a test's output. +/// +/// - returns: The string that is returned can be +/// customized per type by conforming a type to the `TestOutputStringConvertible` +/// protocol. When stringifying a non-`TestOutputStringConvertible` type, this +/// function will return the value's debug description and then its +/// normal description if available and in that order. Otherwise it +/// will return the result of constructing a string from the value. +/// +/// - SeeAlso: `TestOutputStringConvertible` +public func stringify(_ value: T) -> String { + if let value = value as? TestOutputStringConvertible { + return value.testDescription + } + + if let value = value as? CustomDebugStringConvertible { + return value.debugDescription + } + + return String(describing: value) +} + +/// -SeeAlso: `stringify(value: T)` +public func stringify(_ value: T?) -> String { + if let unboxed = value { + return stringify(unboxed) + } + return "nil" +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@objc public class NMBStringer: NSObject { + @objc public class func stringify(_ obj: Any?) -> String { + return Nimble.stringify(obj) + } +} +#endif + +// MARK: Collection Type Stringers + +/// Attempts to generate a pretty type string for a given value. If the value is of a Objective-C +/// collection type, or a subclass thereof, (e.g. `NSArray`, `NSDictionary`, etc.). +/// This function will return the type name of the root class of the class cluster for better +/// readability (e.g. `NSArray` instead of `__NSArrayI`). +/// +/// For values that don't have a type of an Objective-C collection, this function returns the +/// default type description. +/// +/// - parameter value: A value that will be used to determine a type name. +/// +/// - returns: The name of the class cluster root class for Objective-C collection types, or the +/// the `dynamicType` of the value for values of any other type. +public func prettyCollectionType(_ value: T) -> String { + switch value { + case is NSArray: + return String(describing: NSArray.self) + case is NSDictionary: + return String(describing: NSDictionary.self) + case is NSSet: + return String(describing: NSSet.self) + case is NSIndexSet: + return String(describing: NSIndexSet.self) + default: + return String(describing: value) + } +} + +/// Returns the type name for a given collection type. This overload is used by Swift +/// collection types. +/// +/// - parameter collection: A Swift `CollectionType` value. +/// +/// - returns: A string representing the `dynamicType` of the value. +public func prettyCollectionType(_ collection: T) -> String { + return String(describing: type(of: collection)) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h new file mode 100644 index 0000000..7439889 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h @@ -0,0 +1,14 @@ +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker") +@interface CurrentTestCaseTracker : NSObject ++ (CurrentTestCaseTracker *)sharedInstance; +@end + +@interface CurrentTestCaseTracker (Register) @end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..9170541 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,389 @@ +#import + +@class NMBExpectation; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; +@protocol NMBMatcher; + + +NS_ASSUME_NONNULL_BEGIN + + +#define NIMBLE_OVERLOADABLE __attribute__((overloadable)) +#define NIMBLE_EXPORT FOUNDATION_EXPORT +#define NIMBLE_EXPORT_INLINE FOUNDATION_STATIC_INLINE + +#define NIMBLE_VALUE_OF(VAL) ({ \ + __typeof__((VAL)) val = (VAL); \ + [NSValue valueWithBytes:&val objCType:@encode(__typeof__((VAL)))]; \ +}) + +#ifdef NIMBLE_DISABLE_SHORT_SYNTAX +#define NIMBLE_SHORT(PROTO, ORIGINAL) +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) +#else +#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); } +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE NIMBLE_OVERLOADABLE PROTO { return (ORIGINAL); } +#endif + + + +#define DEFINE_NMB_EXPECT_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBExpectation *NMB_expect(TYPE(^actualBlock)(void), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(void), NSString *file, NSUInteger line); + + // overloaded dispatch for nils - expect(nil) + DEFINE_NMB_EXPECT_OVERLOAD(void*, nil) + DEFINE_NMB_EXPECT_OVERLOAD(NSRange, NIMBLE_VALUE_OF(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(float, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(double, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned char, @(actualBlock())) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_NMB_EXPECT_OVERLOAD(BOOL, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char *, @(actualBlock())) + + +#undef DEFINE_NMB_EXPECT_OVERLOAD + + + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line); + + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_equal(TYPE expectedValue) { \ + return NMB_equal((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id equal(TYPE expectedValue), NMB_equal(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_equal(__nullable id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id equal(__nullable id expectedValue), + NMB_equal(expectedValue)); + + // overloaded dispatch for nils - expect(nil) + DEFINE_OVERLOAD(void*__nullable, (id)nil) + DEFINE_OVERLOAD(NSRange, NIMBLE_VALUE_OF(expectedValue)) + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_OVERLOAD(BOOL, @(expectedValue)) + DEFINE_OVERLOAD(char *, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_haveCount(TYPE expectedValue) { \ + return NMB_haveCount((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id haveCount(TYPE expectedValue), \ + NMB_haveCount(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_haveCount(id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id haveCount(id expectedValue), + NMB_haveCount(expectedValue)); + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ + return NMB_beCloseTo((NSNumber *)(EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ + NMB_beCloseTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), + NMB_beCloseTo(expectedValue)); + + // it would be better to only overload float & double, but zero becomes ambigious + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAnInstanceOf(Class expectedClass) { + return NMB_beAnInstanceOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAKindOf(Class expectedClass) { + return NMB_beAKindOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE id beginWith(id itemElementOrSubstring) { + return NMB_beginWith(itemElementOrSubstring); +} + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThan(TYPE expectedValue) { \ + return NMB_beGreaterThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThan(NSNumber *expectedValue) { + return NMB_beGreaterThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beGreaterThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThanOrEqualTo(TYPE expectedValue), \ + NMB_beGreaterThanOrEqualTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beGreaterThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(id beIdenticalTo(id expectedInstance), + NMB_beIdenticalTo(expectedInstance)); + +NIMBLE_EXPORT id NMB_be(id expectedInstance); +NIMBLE_SHORT(id be(id expectedInstance), + NMB_be(expectedInstance)); + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThan(TYPE expectedValue) { \ + return NMB_beLessThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThan(TYPE expectedValue), \ + NMB_beLessThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThan(NSNumber *expectedValue) { + return NMB_beLessThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beLessThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThanOrEqualTo(TYPE expectedValue), \ + NMB_beLessThanOrEqualTo(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beLessThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beTruthy(void); +NIMBLE_SHORT(id beTruthy(void), + NMB_beTruthy()); + +NIMBLE_EXPORT id NMB_beFalsy(void); +NIMBLE_SHORT(id beFalsy(void), + NMB_beFalsy()); + +NIMBLE_EXPORT id NMB_beTrue(void); +NIMBLE_SHORT(id beTrue(void), + NMB_beTrue()); + +NIMBLE_EXPORT id NMB_beFalse(void); +NIMBLE_SHORT(id beFalse(void), + NMB_beFalse()); + +NIMBLE_EXPORT id NMB_beNil(void); +NIMBLE_SHORT(id beNil(void), + NMB_beNil()); + +NIMBLE_EXPORT id NMB_beEmpty(void); +NIMBLE_SHORT(id beEmpty(void), + NMB_beEmpty()); + +NIMBLE_EXPORT id 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 NMB_containElementSatisfying(BOOL(^predicate)(id)); +NIMBLE_SHORT(id containElementSatisfying(BOOL(^predicate)(id)), + NMB_containElementSatisfying(predicate)); + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(id endWith(id itemElementOrSubstring), + NMB_endWith(itemElementOrSubstring)); + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), + NMB_raiseException()); + +NIMBLE_EXPORT id NMB_match(id expectedValue); +NIMBLE_SHORT(id match(id expectedValue), + NMB_match(expectedValue)); + +NIMBLE_EXPORT id NMB_allPass(id matcher); +NIMBLE_SHORT(id allPass(id matcher), + NMB_allPass(matcher)); + +NIMBLE_EXPORT id 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 NMB_satisfyAllOfWithMatchers(id matchers); +#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__]) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__) +#endif + +// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__, +// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout +// and action arguments. See https://github.com/Quick/Quick/pull/185 for details. +typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void))); +typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void))); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line); +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +#define NMB_waitUntilTimeout NMB_waitUntilTimeoutBuilder(@(__FILE__), __LINE__) +#define NMB_waitUntil NMB_waitUntilBuilder(@(__FILE__), __LINE__) + +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define expect(...) NMB_expect(^{ return (__VA_ARGS__); }, @(__FILE__), __LINE__) +#define expectAction(BLOCK) NMB_expectAction((BLOCK), @(__FILE__), __LINE__) +#define failWithMessage(msg) NMB_failWithMessage(msg, @(__FILE__), __LINE__) +#define fail() failWithMessage(@"fail() always fails") + + +#define waitUntilTimeout NMB_waitUntilTimeout +#define waitUntil NMB_waitUntil + +#undef NIMBLE_VALUE_OF + +#endif + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..4b099ac --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,169 @@ +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +SWIFT_CLASS("_TtC6Nimble7NMBWait") +@interface NMBWait : NSObject + ++ (void)untilTimeout:(NSTimeInterval)timeout file:(NSString *)file line:(NSUInteger)line action:(void (^ _Nonnull)(void (^ _Nonnull)(void)))action; ++ (void)untilFile:(NSString *)file line:(NSUInteger)line action:(void (^ _Nonnull)(void (^ _Nonnull)(void)))action; + +@end + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(void), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line) { + return NMB_expect(^id{ + actualBlock(); + return nil; + }, file, line); +} + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line) { + return [NMBExpectation failWithMessage:msg file:file line:line]; +} + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass) { + return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass) { + return [NMBObjCMatcher beAKindOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001]; +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring) { + return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT id NMB_be(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beTruthy() { + return [NMBObjCMatcher beTruthyMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalsy() { + return [NMBObjCMatcher beFalsyMatcher]; +} + +NIMBLE_EXPORT id NMB_beTrue() { + return [NMBObjCMatcher beTrueMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalse() { + return [NMBObjCMatcher beFalseMatcher]; +} + +NIMBLE_EXPORT id NMB_beNil() { + return [NMBObjCMatcher beNilMatcher]; +} + +NIMBLE_EXPORT id NMB_beEmpty() { + return [NMBObjCMatcher beEmptyMatcher]; +} + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) { + NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; + + if (itemOrSubstring) { + [itemOrSubstringArray addObject:itemOrSubstring]; + + va_list args; + va_start(args, itemOrSubstring); + id next; + while ((next = va_arg(args, id))) { + [itemOrSubstringArray addObject:next]; + } + va_end(args); + } + + return [NMBObjCMatcher containMatcher:itemOrSubstringArray]; +} + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)) { + return [NMBObjCMatcher containElementSatisfyingMatcher:predicate]; +} + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring) { + return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_equal(__nullable id expectedValue) { + return [NMBObjCMatcher equalMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_haveCount(id expectedValue) { + return [NMBObjCMatcher haveCountMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_match(id expectedValue) { + return [NMBObjCMatcher matchMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_allPass(id expectedValue) { + return [NMBObjCMatcher allPassMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAnyOfMatcher:matchers]; +} + +NIMBLE_EXPORT id NMB_satisfyAllOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAllOfMatcher:matchers]; +} + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..e6e0272 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h @@ -0,0 +1,11 @@ +#import +#import + +@interface NMBExceptionCapture : NSObject + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..3381047 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m @@ -0,0 +1,35 @@ +#import "NMBExceptionCapture.h" + +@interface NMBExceptionCapture () +@property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); +@property (nonatomic, copy) void(^ _Nullable finally)(void); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(void(^ _Nonnull)(void))unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..7938bca --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h @@ -0,0 +1,18 @@ +@class NSString; + +/** + * Returns a string appropriate for displaying in test output + * from the provided value. + * + * @param anyObject A value that will show up in a test's output. + * + * @return The string that is returned can be + * customized per type by conforming a type to the `TestOutputStringConvertible` + * protocol. When stringifying a non-`TestOutputStringConvertible` type, this + * function will return the value's debug description and then its + * normal description if available and in that order. Otherwise it + * will return the result of constructing a string from the value. + * + * @see `TestOutputStringConvertible` + */ +extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..31a80d6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,11 @@ +#import "NMBStringify.h" + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..35f26fd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -0,0 +1,78 @@ +#import "CurrentTestCaseTracker.h" +#import +#import + +#pragma mark - Method Swizzling + +/// Swaps the implementations between two instance methods. +/// +/// @param class The class containing `originalSelector`. +/// @param originalSelector Original method to replace. +/// @param replacementSelector Replacement method. +void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method replacementMethod = class_getInstanceMethod(class, replacementSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(replacementMethod), + method_getTypeEncoding(replacementMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + replacementSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, replacementMethod); + } +} + +#pragma mark - Private + +@interface XCTestObservationCenter (Private) +- (void)_addLegacyTestObserver:(id)observer; +@end + +@implementation XCTestObservationCenter (Register) + +/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary +/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early +/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. +/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, +/// falling back to registering after the first normal observer if this private method ever changes. ++ (void)load { + if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { + // Swizzle -_addLegacyTestObserver: + swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); + } else { + // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented + swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); + } +} + +#pragma mark - Replacement Methods + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +- (void)NMB_original__addLegacyTestObserver:(id)observer { + [self NMB_original__addLegacyTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) +- (void)NMB_original_addTestObserver:(id)observer { + [self NMB_original_addTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml new file mode 100644 index 0000000..f003326 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml @@ -0,0 +1,2 @@ +disabled_rules: + - line_length diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift @@ -0,0 +1,37 @@ +import XCTest +@testable import NimbleTests + +// This is the entry point for NimbleTests on Linux + +XCTMain([ + testCase(AsyncTest.allTests), + testCase(SynchronousTest.allTests), + testCase(UserDescriptionTest.allTests), + + // Matchers + testCase(AllPassTest.allTests), + testCase(BeAKindOfSwiftTest.allTests), + testCase(BeAnInstanceOfTest.allTests), + testCase(BeCloseToTest.allTests), + testCase(BeginWithTest.allTests), + testCase(BeGreaterThanOrEqualToTest.allTests), + testCase(BeGreaterThanTest.allTests), + testCase(BeIdenticalToObjectTest.allTests), + testCase(BeIdenticalToTest.allTests), + testCase(BeLessThanOrEqualToTest.allTests), + testCase(BeLessThanTest.allTests), + testCase(BeTruthyTest.allTests), + testCase(BeTrueTest.allTests), + testCase(BeFalsyTest.allTests), + testCase(BeFalseTest.allTests), + testCase(BeNilTest.allTests), + testCase(ContainTest.allTests), + testCase(EndWithTest.allTests), + testCase(EqualTest.allTests), + testCase(HaveCountTest.allTests), + testCase(MatchTest.allTests), + // testCase(RaisesExceptionTest.allTests), + testCase(ThrowErrorTest.allTests), + testCase(SatisfyAnyOfTest.allTests), + testCase(PostNotificationTest.allTests), +]) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..c44b9e6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,257 @@ +import Dispatch +import Foundation +import XCTest +import Nimble + +final class AsyncTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AsyncTest) -> () throws -> Void)] { + return [ + ("testToEventuallyPositiveMatches", testToEventuallyPositiveMatches), + ("testToEventuallyNegativeMatches", testToEventuallyNegativeMatches), + ("testWaitUntilWithCustomDefaultsTimeout", testWaitUntilWithCustomDefaultsTimeout), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ("testSubjectUnderTestIsReleasedFromMemory", testSubjectUnderTestIsReleasedFromMemory), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testToEventuallyPositiveMatches() { + var value = 0 + deferToMainQueue { value = 1 } + expect { value }.toEventually(equal(1)) + + deferToMainQueue { value = 0 } + expect { value }.toEventuallyNot(equal(1)) + } + + func testToEventuallyNegativeMatches() { + let value = 0 + failsWithErrorMessage("expected to eventually not equal <0>, got <0>") { + expect { value }.toEventuallyNot(equal(0)) + } + failsWithErrorMessage("expected to eventually equal <1>, got <0>") { + expect { value }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventuallyNot(equal(0)) + } + } + + func testToEventuallyWithCustomDefaultTimeout() { + AsyncDefaults.Timeout = 2 + defer { + AsyncDefaults.Timeout = 1 + } + + var value = 0 + + let sleepThenSetValueTo: (Int) -> Void = { newValue in + Thread.sleep(forTimeInterval: 1.1) + value = newValue + } + + var asyncOperation: () -> Void = { sleepThenSetValueTo(1) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventually(equal(1)) + + asyncOperation = { sleepThenSetValueTo(0) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventuallyNot(equal(1)) + } + + func testWaitUntilWithCustomDefaultsTimeout() { + AsyncDefaults.Timeout = 5 + defer { + AsyncDefaults.Timeout = 1 + } + waitUntil { done in + Thread.sleep(forTimeInterval: 4.8) + done() + } + } + + func testWaitUntilPositiveMatches() { + waitUntil { done in + done() + } + waitUntil { done in + deferToMainQueue { + done() + } + } + } + + func testWaitUntilTimesOutIfNotCalled() { + failsWithErrorMessage("Waited more than 1.0 second") { + waitUntil(timeout: 1) { _ in return } + } + } + + func testWaitUntilTimesOutWhenExceedingItsTime() { + var waiting = true + failsWithErrorMessage("Waited more than 0.01 seconds") { + waitUntil(timeout: 0.01) { done in + let asyncOperation: () -> Void = { + Thread.sleep(forTimeInterval: 0.1) + done() + waiting = false + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + } + } + + // "clear" runloop to ensure this test doesn't poison other tests + repeat { + RunLoop.main.run(until: Date().addingTimeInterval(0.2)) + } while(waiting) + } + + func testWaitUntilNegativeMatches() { + failsWithErrorMessage("expected to equal <2>, got <1>") { + waitUntil { done in + Thread.sleep(forTimeInterval: 0.1) + expect(1).to(equal(2)) + done() + } + } + } + + func testWaitUntilDetectsStalledMainThreadActivity() { + let msg = "-waitUntil() timed out but was unable to run the timeout handler because the main thread is unresponsive (0.5 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." + failsWithErrorMessage(msg) { + waitUntil(timeout: 1) { done in + Thread.sleep(forTimeInterval: 5.0) + done() + } + } + } + + func testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed() { + // Currently we are unable to catch Objective-C exceptions when built by the Swift Package Manager +#if !SWIFT_PACKAGE + let referenceLine = #line + 9 + var msg = "Unexpected exception raised: Nested async expectations are not allowed " + msg += "to avoid creating flaky tests." + msg += "\n\n" + msg += "The call to\n\t" + msg += "expect(...).toEventually(...) at \(#file):\(referenceLine + 7)\n" + msg += "triggered this exception because\n\t" + msg += "waitUntil(...) at \(#file):\(referenceLine + 1)\n" + msg += "is currently managing the main run loop." + failsWithErrorMessage(msg) { // reference line + waitUntil(timeout: 2.0) { done in + var protected: Int = 0 + DispatchQueue.main.async { + protected = 1 + } + + expect(protected).toEventually(equal(1)) + done() + } + } +#endif + } + + func testWaitUntilErrorsIfDoneIsCalledMultipleTimes() { + failsWithErrorMessage("waitUntil(..) expects its completion closure to be only called once") { + waitUntil { done in + deferToMainQueue { + done() + done() + } + } + } + } + + func testWaitUntilMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + waitUntil { done in done() } + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + func testToEventuallyMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + expect(1).toEventually(equal(2)) + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + final class ClassUnderTest { + var deinitCalled: (() -> Void)? + var count = 0 + deinit { deinitCalled?() } + } + + func testSubjectUnderTestIsReleasedFromMemory() { + var subject: ClassUnderTest? = ClassUnderTest() + + if let sub = subject { + expect(sub.count).toEventually(equal(0), timeout: 0.1) + expect(sub.count).toEventuallyNot(equal(1), timeout: 0.1) + } + + waitUntil(timeout: 0.5) { done in + subject?.deinitCalled = { + done() + } + + deferToMainQueue { subject = nil } + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift @@ -0,0 +1,7 @@ +import Foundation + +class ObjectWithLazyProperty { + init() {} + lazy var value: String = "hello" + lazy var anotherValue: String = { return "world" }() +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..08a67c6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +extension XCTestCaseProvider { + var allTestNames: [String] { + return type(of: self).allTests.map({ name, _ in + return name + }) + } +} + +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } +} + +extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..a1bbc68 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,100 @@ +import Dispatch +import Foundation +@testable import Nimble +import XCTest + +func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () throws -> Void) { + var filePath = file + var lineNumber = line + + let recorder = AssertionRecorder() + withAssertionHandler(recorder, closure: closure) + + for msg in messages { + var lastFailure: AssertionRecord? + var foundFailureMessage = false + + for assertion in recorder.assertions where assertion.message.stringValue == msg && !assertion.success { + lastFailure = assertion + foundFailureMessage = true + break + } + + if foundFailureMessage { + continue + } + + if preferOriginalSourceLocation { + if let failure = lastFailure { + filePath = failure.location.file + lineNumber = failure.location.line + } + } + + let message: String + if let lastFailure = lastFailure { + message = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\"" + } else { + let knownFailures = recorder.assertions.filter { !$0.success }.map { $0.message.stringValue } + let knownFailuresJoined = knownFailures.joined(separator: ", ") + message = "Expected error message (\(msg)), got (\(knownFailuresJoined))\n\nAssertions Received:\n\(recorder.assertions)" + } + NimbleAssertionHandler.assert(false, + message: FailureMessage(stringValue: message), + location: SourceLocation(file: filePath, line: lineNumber)) + } +} + +func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + return failsWithErrorMessage( + [message], + file: file, + line: line, + preferOriginalSourceLocation: preferOriginalSourceLocation, + closure: closure + ) +} + +func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + failsWithErrorMessage("\(message) (use beNil() to match nils)", file: file, line: line, preferOriginalSourceLocation: preferOriginalSourceLocation, closure: closure) +} + +func deferToMainQueue(action: @escaping () -> Void) { + DispatchQueue.main.async { + Thread.sleep(forTimeInterval: 0.01) + action() + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +public class NimbleHelper: NSObject { + @objc public class func expectFailureMessage(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessages(_ messages: [NSString], block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(messages.map({String(describing: $0)}), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessageForNil(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessageForNil(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } +} +#endif + +extension Date { + init(dateTimeString: String) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + let date = dateFormatter.date(from: dateTimeString)! + self.init(timeInterval: 0, since: date) + } +} + +extension NSDate { + convenience init(dateTimeString: String) { + let date = Date(dateTimeString: dateTimeString) + self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift @@ -0,0 +1,9 @@ +import Foundation + +#if os(Linux) + extension NSNotification.Name { + init(_ rawValue: String) { + self.init(rawValue: rawValue) + } + } +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift @@ -0,0 +1,126 @@ +import XCTest +import Nimble + +/// Add operators to `Optional` for conforming `Comparable` that removed in Swift 3.0 +extension Optional where Wrapped: Comparable { + static func < (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } + } + + static func > (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } + } + + static func <= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l <= r + default: + return !(rhs < lhs) + } + } + + static func >= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } + } +} + +final class AllPassTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AllPassTest) -> () throws -> Void)] { + return [ + ("testAllPassArray", testAllPassArray), + ("testAllPassMatcher", testAllPassMatcher), + ("testAllPassCollectionsWithOptionalsDontWork", testAllPassCollectionsWithOptionalsDontWork), + ("testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer", testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer), + ("testAllPassSet", testAllPassSet), + ("testAllPassWithNilAsExpectedValue", testAllPassWithNilAsExpectedValue), + ] + } + + func testAllPassArray() { + expect([1, 2, 3, 4]).to(allPass({$0 < 5})) + expect([1, 2, 3, 4]).toNot(allPass({$0 > 5})) + + failsWithErrorMessage( + "expected to all pass a condition, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass({$0 < 3})) + } + failsWithErrorMessage("expected to not all pass a condition") { + expect([1, 2, 3, 4]).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage( + "expected to all be something, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass("be something", {$0 < 3})) + } + failsWithErrorMessage("expected to not all be something") { + expect([1, 2, 3, 4]).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassMatcher() { + expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) + expect([1, 2, 3, 4]).toNot(allPass(beGreaterThan(5))) + + failsWithErrorMessage( + "expected to all be less than <3>, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass(beLessThan(3))) + } + failsWithErrorMessage("expected to not all be less than <5>") { + expect([1, 2, 3, 4]).toNot(allPass(beLessThan(5))) + } + } + + func testAllPassCollectionsWithOptionalsDontWork() { + failsWithErrorMessage("expected to all be nil, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass(beNil())) + } + failsWithErrorMessage("expected to all pass a condition, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass({$0 == nil})) + } + } + + func testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer() { + expect([nil, nil, nil] as [Int?]).to(allPass({$0! == nil})) + expect([nil, 1, nil] as [Int?]).toNot(allPass({$0! == nil})) + expect([1, 1, 1] as [Int?]).to(allPass({$0! == 1})) + expect([1, 1, nil] as [Int?]).toNot(allPass({$0! == 1})) + expect([1, 2, 3] as [Int?]).to(allPass({$0! < 4})) + expect([1, 2, 3] as [Int?]).toNot(allPass({$0! < 3})) + expect([1, 2, nil] as [Int?]).to(allPass({$0! < 3})) + } + + func testAllPassSet() { + expect(Set([1, 2, 3, 4])).to(allPass({$0 < 5})) + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 > 5})) + + failsWithErrorMessage("expected to not all pass a condition") { + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage("expected to not all be something") { + expect(Set([1, 2, 3, 4])).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassWithNilAsExpectedValue() { + failsWithErrorMessageForNil("expected to all pass") { + expect(nil as [Int]?).to(allPass(beLessThan(5))) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..bb9041b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +private class TestNull: NSNull {} +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfSwiftTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + enum TestEnum { + case one, two + } + + func testPositiveMatch() { + expect(1).to(beAKindOf(Int.self)) + expect(1).toNot(beAKindOf(String.self)) + expect("turtle string").to(beAKindOf(String.self)) + expect("turtle string").toNot(beAKindOf(TestClassConformingToProtocol.self)) + + expect(TestEnum.one).to(beAKindOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAKindOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).to(beAKindOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAKindOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAKindOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).to(beAKindOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAKindOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessage("expected to not be a kind of Int, got ") { + expect(1).toNot(beAKindOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to not be a kind of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).toNot(beAKindOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be a kind of String, got ") { + expect(1).to(beAKindOf(String.self)) + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfObjCTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + func testPositiveMatch() { + expect(TestNull()).to(beAKindOf(NSNull.self)) + expect(NSObject()).to(beAKindOf(NSObject.self)) + expect(NSNumber(value: 1)).toNot(beAKindOf(NSDate.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be a kind of NSNull, got ") { + expect(nil as NSNull?).toNot(beAKindOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be a kind of NSString, got ") { + expect(nil as NSString?).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to be a kind of NSString, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to not be a kind of NSNumber, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).toNot(beAKindOf(NSNumber.self)) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..aeea28a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAnInstanceOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAnInstanceOfTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testPositiveMatchSwiftTypes", testPositiveMatchSwiftTypes), + ("testFailureMessages", testFailureMessages), + ("testFailureMessagesSwiftTypes", testFailureMessagesSwiftTypes), + ] + } + + func testPositiveMatch() { + expect(NSNull()).to(beAnInstanceOf(NSNull.self)) + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(NSDate.self)) + } + + enum TestEnum { + case one, two + } + + func testPositiveMatchSwiftTypes() { + expect(1).to(beAnInstanceOf(Int.self)) + expect("test").to(beAnInstanceOf(String.self)) + + expect(TestEnum.one).to(beAnInstanceOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAnInstanceOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAnInstanceOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be an instance of NSNull, got ") { + expect(nil as NSNull?).toNot(beAnInstanceOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be an instance of NSString, got ") { + expect(nil as NSString?).to(beAnInstanceOf(NSString.self)) + } +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let numberTypeName = "__NSCFNumber" +#else + let numberTypeName = "NSNumber" +#endif + failsWithErrorMessage("expected to be an instance of NSString, got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).to(beAnInstanceOf(NSString.self)) + } + failsWithErrorMessage("expected to not be an instance of \(numberTypeName), got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(type(of: NSNumber(value: 1)))) + } + } + + func testFailureMessagesSwiftTypes() { + failsWithErrorMessage("expected to not be an instance of Int, got ") { + expect(1).toNot(beAnInstanceOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to be an instance of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).to(beAnInstanceOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be an instance of String, got ") { + expect(1).to(beAnInstanceOf(String.self)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..cb7a3ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift @@ -0,0 +1,160 @@ +import Foundation +import XCTest +import Nimble + +final class BeCloseToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeCloseToTest) -> () throws -> Void)] { + return [ + ("testBeCloseTo", testBeCloseTo), + ("testBeCloseToWithin", testBeCloseToWithin), + ("testBeCloseToWithNSNumber", testBeCloseToWithNSNumber), + ("testBeCloseToWithDate", testBeCloseToWithDate), + ("testBeCloseToWithNSDate", testBeCloseToWithNSDate), + ("testBeCloseToOperator", testBeCloseToOperator), + ("testBeCloseToWithinOperator", testBeCloseToWithinOperator), + ("testPlusMinusOperator", testPlusMinusOperator), + ("testBeCloseToOperatorWithDate", testBeCloseToOperatorWithDate), + ("testBeCloseToWithinOperatorWithDate", testBeCloseToWithinOperatorWithDate), + ("testPlusMinusOperatorWithDate", testPlusMinusOperatorWithDate), + ("testBeCloseToArray", testBeCloseToArray), + ("testBeCloseToWithCGFloat", testBeCloseToWithCGFloat), + ] + } + + func testBeCloseTo() { + expect(1.2).to(beCloseTo(1.2001)) + expect(1.2 as CDouble).to(beCloseTo(1.2001)) + expect(1.2 as Float).to(beCloseTo(1.2001)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 0.0001), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001)) + } + } + + func testBeCloseToWithin() { + expect(1.2).to(beCloseTo(9.300, within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithNSNumber() { + expect(NSNumber(value: 1.2)).to(beCloseTo(9.300, within: 10)) + expect(NSNumber(value: 1.2)).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + expect(1.2).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithCGFloat() { + expect(CGFloat(1.2)).to(beCloseTo(1.2001)) + expect(CGFloat(1.2)).to(beCloseTo(CGFloat(1.2001))) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(Date(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToWithNSDate() { + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(NSDate(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = NSDate(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToOperator() { + expect(1.2) ≈ 1.2001 + expect(1.2 as CDouble) ≈ 1.2001 + + failsWithErrorMessage("expected to be close to <1.2002> (within 0.0001), got <1.2>") { + expect(1.2) ≈ 1.2002 + } + } + + func testBeCloseToWithinOperator() { + expect(1.2) ≈ (9.300, 10) + expect(1.2) == (9.300, 10) + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ (1.0, 0.1) + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == (1.0, 0.1) + } + } + + func testPlusMinusOperator() { + expect(1.2) ≈ 9.300 ± 10 + expect(1.2) == 9.300 ± 10 + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ 1.0 ± 0.1 + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == 1.0 ± 0.1 + } + } + + func testBeCloseToOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:00") + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.0001), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate + } + } + + func testBeCloseToWithinOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (expectedDate, 0.004) + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (expectedDate, 0.004) + } + } + + func testPlusMinusOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate ± 0.004 + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == expectedDate ± 0.004 + } + } + + func testBeCloseToArray() { + expect([0.0, 1.1, 2.2]) ≈ [0.0001, 1.1001, 2.2001] + expect([0.0, 1.1, 2.2]).to(beCloseTo([0.1, 1.2, 2.3], within: 0.1)) + + failsWithErrorMessage("expected to be close to <[0, 1]> (each within 0.0001), got <[0, 1.1]>") { + expect([0.0, 1.1]) ≈ [0.0, 1.0] + } + failsWithErrorMessage("expected to be close to <[0.2, 1.2]> (each within 0.1), got <[0, 1.1]>") { + expect([0.0, 1.1]).to(beCloseTo([0.2, 1.2], within: 0.1)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..067ddeb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift @@ -0,0 +1,82 @@ +import Foundation +import XCTest +import Nimble + +final class BeEmptyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeEmptyTest) -> () throws -> Void)] { + return [ + ("testBeEmptyPositive", testBeEmptyPositive), + ("testBeEmptyNegative", testBeEmptyNegative), + ] + } + + func testBeEmptyPositive() { + expect([] as [Int]).to(beEmpty()) + expect([1]).toNot(beEmpty()) + + expect([] as [CInt]).to(beEmpty()) + expect([1] as [CInt]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary() as? [Int: Int]).to(beEmpty()) + expect(NSDictionary(object: 1, forKey: 1 as NSNumber) as? [Int: Int]).toNot(beEmpty()) +#endif + + expect([Int: Int]()).to(beEmpty()) + expect(["hi": 1]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray() as? [Int]).to(beEmpty()) + expect(NSArray(array: [1]) as? [Int]).toNot(beEmpty()) +#endif + + expect(NSSet()).to(beEmpty()) + expect(NSSet(array: [NSNumber(value: 1)])).toNot(beEmpty()) + + expect(NSIndexSet()).to(beEmpty()) + expect(NSIndexSet(index: 1)).toNot(beEmpty()) + + expect(NSString()).to(beEmpty()) + expect(NSString(string: "hello")).toNot(beEmpty()) + + expect("").to(beEmpty()) + expect("foo").toNot(beEmpty()) + } + + func testBeEmptyNegative() { + failsWithErrorMessageForNil("expected to be empty, got ") { + expect(nil as NSString?).to(beEmpty()) + } + failsWithErrorMessageForNil("expected to not be empty, got ") { + expect(nil as [CInt]?).toNot(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSArray()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <[1]>") { + expect([1]).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <{()}>") { + expect(NSSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <{(1)}>") { + expect(NSSet(object: NSNumber(value: 1))).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSIndexSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <(1)>") { + expect(NSIndexSet(index: 1)).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <>") { + expect("").toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got ") { + expect("foo").to(beEmpty()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..bd73361 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testGreaterThanOrEqualTo", testGreaterThanOrEqualTo), + ("testGreaterThanOrEqualToOperator", testGreaterThanOrEqualToOperator), + ] + } + + func testGreaterThanOrEqualTo() { + expect(10).to(beGreaterThanOrEqualTo(10)) + expect(10).to(beGreaterThanOrEqualTo(2)) + expect(1).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 1)).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 2)).to(beGreaterThanOrEqualTo(NSNumber(value: 2))) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(1).to(beGreaterThanOrEqualTo(NSNumber(value: 0))) +#endif + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <0>") { + expect(0).to(beGreaterThanOrEqualTo(2)) + return + } + failsWithErrorMessage("expected to not be greater than or equal to <1>, got <1>") { + expect(1).toNot(beGreaterThanOrEqualTo(1)) + return + } + failsWithErrorMessageForNil("expected to be greater than or equal to <-2>, got ") { + expect(nil as Int?).to(beGreaterThanOrEqualTo(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than or equal to <1>, got ") { + expect(nil as Int?).toNot(beGreaterThanOrEqualTo(1)) + } + } + + func testGreaterThanOrEqualToOperator() { + expect(0) >= 0 + expect(1) >= 0 + expect(NSNumber(value: 1)) >= 1 + expect(NSNumber(value: 1)) >= NSNumber(value: 1) + expect(2.5) >= 2.5 + expect(2.5) >= 2 + expect(Float(2.5)) >= Float(2.5) + expect(Float(2.5)) >= 2 + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <1>") { + expect(1) >= 2 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..9c33e4b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanTest) -> () throws -> Void)] { + return [ + ("testGreaterThan", testGreaterThan), + ("testGreaterThanOperator", testGreaterThanOperator), + ] + } + + func testGreaterThan() { + expect(10).to(beGreaterThan(2)) + expect(1).toNot(beGreaterThan(2)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 3)).to(beGreaterThan(2)) +#else + expect(NSNumber(value: 3)).to(beGreaterThan(2 as NSNumber)) +#endif + expect(NSNumber(value: 1)).toNot(beGreaterThan(NSNumber(value: 2))) + + failsWithErrorMessage("expected to be greater than <2>, got <0>") { + expect(0).to(beGreaterThan(2)) + } + failsWithErrorMessage("expected to not be greater than <0>, got <1>") { + expect(1).toNot(beGreaterThan(0)) + } + failsWithErrorMessageForNil("expected to be greater than <-2>, got ") { + expect(nil as Int?).to(beGreaterThan(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than <0>, got ") { + expect(nil as Int?).toNot(beGreaterThan(0)) + } + } + + func testGreaterThanOperator() { + expect(1) > 0 + expect(NSNumber(value: 1)) > NSNumber(value: 0) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 1)) > 0 +#else + expect(NSNumber(value: 1)) > 0 as NSNumber +#endif + expect(2.5) > 1.5 + expect(Float(2.5)) > Float(1.5) + + failsWithErrorMessage("expected to be greater than <2>, got <1>") { + expect(1) > 2 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift @@ -0,0 +1,64 @@ +import Foundation +import XCTest +import Nimble + +final class BeIdenticalToObjectTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToObjectTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testFailsOnNils", testFailsOnNils), + ("testOperators", testOperators), + ] + } + + private class BeIdenticalToObjectTester {} + private let testObjectA = BeIdenticalToObjectTester() + private let testObjectB = BeIdenticalToObjectTester() + + func testBeIdenticalToPositive() { + expect(self.testObjectA).to(beIdenticalTo(testObjectA)) + } + + func testBeIdenticalToNegative() { + expect(self.testObjectA).toNot(beIdenticalTo(testObjectB)) + } + + func testBeIdenticalToPositiveMessage() { + let message = String(describing: NSString(format: "expected to be identical to <%p>, got <%p>", + unsafeBitCast(testObjectB, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).to(beIdenticalTo(self.testObjectB)) + } + } + + func testBeIdenticalToNegativeMessage() { + let message = String(describing: NSString(format: "expected to not be identical to <%p>, got <%p>", + unsafeBitCast(testObjectA, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testFailsOnNils() { + let message1 = String(describing: NSString(format: "expected to be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message1) { + expect(nil as BeIdenticalToObjectTester?).to(beIdenticalTo(self.testObjectA)) + } + + let message2 = String(describing: NSString(format: "expected to not be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message2) { + expect(nil as BeIdenticalToObjectTester?).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testOperators() { + expect(self.testObjectA) === testObjectA + expect(self.testObjectA) !== testObjectB + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..6b629b0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift @@ -0,0 +1,68 @@ +import Foundation +import XCTest +@testable import Nimble + +final class BeIdenticalToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testOperators", testOperators), + ("testBeAlias", testBeAlias), + ] + } + + func testBeIdenticalToPositive() { + let value = NSDate() + expect(value).to(beIdenticalTo(value)) + } + + func testBeIdenticalToNegative() { + expect(NSNumber(value: 1)).toNot(beIdenticalTo(NSString(string: "yo"))) + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + } + + func testBeIdenticalToPositiveMessage() { + let num1 = NSNumber(value: 1) + let num2 = NSNumber(value: 2) + let message = "expected to be identical to \(identityAsString(num2)), got \(identityAsString(num1))" + failsWithErrorMessage(message) { + expect(num1).to(beIdenticalTo(num2)) + } + } + + func testBeIdenticalToNegativeMessage() { + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value2)), got \(identityAsString(value1))" + failsWithErrorMessage(message) { + expect(value1).toNot(beIdenticalTo(value2)) + } + } + + func testOperators() { + let value = NSDate() + expect(value) === value + expect(NSNumber(value: 1)) !== NSNumber(value: 2) + } + + func testBeAlias() { + let value = NSDate() + expect(value).to(be(value)) + expect(NSNumber(value: 1)).toNot(be(NSString(string: "turtles"))) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect([1]).toNot(be([1])) + #else + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + #endif + + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value1)), got \(identityAsString(value2))" + failsWithErrorMessage(message) { + expect(value1).toNot(be(value2)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..428ace4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testLessThanOrEqualTo", testLessThanOrEqualTo), + ("testLessThanOrEqualToOperator", testLessThanOrEqualToOperator), + ] + } + + func testLessThanOrEqualTo() { + expect(10).to(beLessThanOrEqualTo(10)) + expect(2).to(beLessThanOrEqualTo(10)) + expect(2).toNot(beLessThanOrEqualTo(1)) + + expect(NSNumber(value: 2)).to(beLessThanOrEqualTo(10)) + expect(NSNumber(value: 2)).toNot(beLessThanOrEqualTo(1)) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(2).to(beLessThanOrEqualTo(NSNumber(value: 10))) + expect(2).toNot(beLessThanOrEqualTo(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than or equal to <0>, got <2>") { + expect(2).to(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessage("expected to not be less than or equal to <0>, got <0>") { + expect(0).toNot(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessageForNil("expected to be less than or equal to <2>, got ") { + expect(nil as Int?).to(beLessThanOrEqualTo(2)) + return + } + failsWithErrorMessageForNil("expected to not be less than or equal to <-2>, got ") { + expect(nil as Int?).toNot(beLessThanOrEqualTo(-2)) + return + } + } + + func testLessThanOrEqualToOperator() { + expect(0) <= 1 + expect(1) <= 1 + + failsWithErrorMessage("expected to be less than or equal to <1>, got <2>") { + expect(2) <= 1 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..90ba1b9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift @@ -0,0 +1,57 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanTest) -> () throws -> Void)] { + return [ + ("testLessThan", testLessThan), + ("testLessThanOperator", testLessThanOperator), + ] + } + + func testLessThan() { + expect(2).to(beLessThan(10)) + expect(2).toNot(beLessThan(1)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 2)).to(beLessThan(10)) + expect(NSNumber(value: 2)).toNot(beLessThan(1)) + + expect(2).to(beLessThan(NSNumber(value: 10))) + expect(2).toNot(beLessThan(NSNumber(value: 1))) +#else + expect(NSNumber(value: 2)).to(beLessThan(10 as NSNumber)) + expect(NSNumber(value: 2)).toNot(beLessThan(1 as NSNumber)) + + expect(2 as NSNumber).to(beLessThan(NSNumber(value: 10))) + expect(2 as NSNumber).toNot(beLessThan(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than <0>, got <2>") { + expect(2).to(beLessThan(0)) + } + failsWithErrorMessage("expected to not be less than <1>, got <0>") { + expect(0).toNot(beLessThan(1)) + } + + failsWithErrorMessageForNil("expected to be less than <2>, got ") { + expect(nil as Int?).to(beLessThan(2)) + } + failsWithErrorMessageForNil("expected to not be less than <-1>, got ") { + expect(nil as Int?).toNot(beLessThan(-1)) + } + } + + func testLessThanOperator() { + expect(0) < 1 +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 0)) < 1 +#else + expect(NSNumber(value: 0)) < 1 as NSNumber +#endif + failsWithErrorMessage("expected to be less than <1>, got <2>") { + expect(2) < 1 + return + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift @@ -0,0 +1,270 @@ +import XCTest +import Nimble +import Foundation + +enum ConvertsToBool: ExpressibleByBooleanLiteral, CustomStringConvertible { + case trueLike, falseLike + + typealias BooleanLiteralType = Bool + + init(booleanLiteral value: Bool) { + switch value { + case true: self = .trueLike + case false: self = .falseLike + } + } + + var boolValue: Bool { + switch self { + case .trueLike: return true + case .falseLike: return false + } + } + + var description: String { + switch self { + case .trueLike: return "TrueLike" + case .falseLike: return "FalseLike" + } + } +} + +final class BeTruthyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTruthyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNonNilTypes", testShouldMatchNonNilTypes), + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchNilTypes", testShouldNotMatchNilTypes), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ("testShouldMatchBoolConvertibleTypesThatConvertToTrue", testShouldMatchBoolConvertibleTypesThatConvertToTrue), + ("testShouldNotMatchBoolConvertibleTypesThatConvertToFalse", testShouldNotMatchBoolConvertibleTypesThatConvertToFalse), + ] + } + + func testShouldMatchNonNilTypes() { + expect(true as Bool?).to(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).to(beTruthy()) + expect(1 as UInt8?).to(beTruthy()) + expect(1 as Int16?).to(beTruthy()) + expect(1 as UInt16?).to(beTruthy()) + expect(1 as Int32?).to(beTruthy()) + expect(1 as UInt32?).to(beTruthy()) + expect(1 as Int64?).to(beTruthy()) + expect(1 as UInt64?).to(beTruthy()) + expect(1 as Float?).to(beTruthy()) + expect(1 as Double?).to(beTruthy()) + expect(1 as Int?).to(beTruthy()) + expect(1 as UInt?).to(beTruthy()) + } + + func testShouldMatchTrue() { + expect(true).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(true).toNot(beTruthy()) + } + } + + func testShouldNotMatchNilTypes() { + expect(false as Bool?).toNot(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).toNot(beTruthy()) + expect(nil as Int8?).toNot(beTruthy()) + expect(nil as UInt8?).toNot(beTruthy()) + expect(nil as Int16?).toNot(beTruthy()) + expect(nil as UInt16?).toNot(beTruthy()) + expect(nil as Int32?).toNot(beTruthy()) + expect(nil as UInt32?).toNot(beTruthy()) + expect(nil as Int64?).toNot(beTruthy()) + expect(nil as UInt64?).toNot(beTruthy()) + expect(nil as Float?).toNot(beTruthy()) + expect(nil as Double?).toNot(beTruthy()) + expect(nil as Int?).toNot(beTruthy()) + expect(nil as UInt?).toNot(beTruthy()) + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(false).to(beTruthy()) + } + } + + func testShouldNotMatchNilBools() { + expect(nil as Bool?).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(nil as Bool?).to(beTruthy()) + } + } + + func testShouldMatchBoolConvertibleTypesThatConvertToTrue() { + expect(ConvertsToBool.trueLike).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(ConvertsToBool.trueLike).toNot(beTruthy()) + } + } + + func testShouldNotMatchBoolConvertibleTypesThatConvertToFalse() { + expect(ConvertsToBool.falseLike).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(ConvertsToBool.falseLike).to(beTruthy()) + } + } +} + +final class BeTrueTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTrueTest) -> () throws -> Void)] { + return [ + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldMatchTrue() { + expect(true).to(beTrue()) + + failsWithErrorMessage("expected to not be true, got ") { + expect(true).toNot(beTrue()) + } + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTrue()) + + failsWithErrorMessage("expected to be true, got ") { + expect(false).to(beTrue()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to not be true, got ") { + expect(nil as Bool?).toNot(beTrue()) + } + + failsWithErrorMessageForNil("expected to be true, got ") { + expect(nil as Bool?).to(beTrue()) + } + } +} + +final class BeFalsyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalsyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNilTypes", testShouldMatchNilTypes), + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldNotMatchNonNilTypes", testShouldNotMatchNonNilTypes), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldMatchNilBools", testShouldMatchNilBools), + ] + } + + func testShouldMatchNilTypes() { + expect(false as Bool?).to(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).to(beFalsy()) + expect(nil as Int8?).to(beFalsy()) + expect(nil as UInt8?).to(beFalsy()) + expect(nil as Int16?).to(beFalsy()) + expect(nil as UInt16?).to(beFalsy()) + expect(nil as Int32?).to(beFalsy()) + expect(nil as UInt32?).to(beFalsy()) + expect(nil as Int64?).to(beFalsy()) + expect(nil as UInt64?).to(beFalsy()) + expect(nil as Float?).to(beFalsy()) + expect(nil as Double?).to(beFalsy()) + expect(nil as Int?).to(beFalsy()) + expect(nil as UInt?).to(beFalsy()) + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalsy()) + + failsWithErrorMessage("expected to be falsy, got ") { + expect(true).to(beFalsy()) + } + } + + func testShouldNotMatchNonNilTypes() { + expect(true as Bool?).toNot(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).toNot(beFalsy()) + expect(1 as UInt8?).toNot(beFalsy()) + expect(1 as Int16?).toNot(beFalsy()) + expect(1 as UInt16?).toNot(beFalsy()) + expect(1 as Int32?).toNot(beFalsy()) + expect(1 as UInt32?).toNot(beFalsy()) + expect(1 as Int64?).toNot(beFalsy()) + expect(1 as UInt64?).toNot(beFalsy()) + expect(1 as Float?).toNot(beFalsy()) + expect(1 as Double?).toNot(beFalsy()) + expect(1 as Int?).toNot(beFalsy()) + expect(1 as UInt?).toNot(beFalsy()) + } + + func testShouldMatchFalse() { + expect(false).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(false).toNot(beFalsy()) + } + } + + func testShouldMatchNilBools() { + expect(nil as Bool?).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(nil as Bool?).toNot(beFalsy()) + } + } +} + +final class BeFalseTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalseTest) -> () throws -> Void)] { + return [ + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalse()) + + failsWithErrorMessage("expected to be false, got ") { + expect(true).to(beFalse()) + } + } + + func testShouldMatchFalse() { + expect(false).to(beFalse()) + + failsWithErrorMessage("expected to not be false, got ") { + expect(false).toNot(beFalse()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to be false, got ") { + expect(nil as Bool?).to(beFalse()) + } + + failsWithErrorMessageForNil("expected to not be false, got ") { + expect(nil as Bool?).toNot(beFalse()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift @@ -0,0 +1,28 @@ +import XCTest +import Nimble + +final class BeNilTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeNilTest) -> () throws -> Void)] { + return [ + ("testBeNil", testBeNil), + ] + } + + func producesNil() -> [Int]? { + return nil + } + + func testBeNil() { + expect(nil as Int?).to(beNil()) + expect(1 as Int?).toNot(beNil()) + expect(self.producesNil()).to(beNil()) + + failsWithErrorMessage("expected to not be nil, got ") { + expect(nil as Int?).toNot(beNil()) + } + + failsWithErrorMessage("expected to be nil, got <1>") { + expect(1 as Int?).to(beNil()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift @@ -0,0 +1,32 @@ +import XCTest +import Nimble + +final class BeVoidTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeVoidTest) -> () throws -> Void)] { + return [ + ("testBeVoid", testBeVoid), + ] + } + + func testBeVoid() { + expect(()).to(beVoid()) + expect(() as ()?).to(beVoid()) + expect(nil as ()?).toNot(beVoid()) + + expect(()) == () + expect(() as ()?) == () + expect(nil as ()?) != () + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(()).toNot(beVoid()) + } + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(() as ()?).toNot(beVoid()) + } + + failsWithErrorMessage("expected to be void, got ") { + expect(nil as ()?).to(beVoid()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..276c7d0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeginWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeginWithTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testNegativeMatches", testNegativeMatches), + ] + } + + func testPositiveMatches() { + expect([1, 2, 3]).to(beginWith(1)) + expect([1, 2, 3]).toNot(beginWith(2)) + + expect("foobar").to(beginWith("foo")) + expect("foobar").toNot(beginWith("oo")) + + expect("foobarfoo").to(beginWith("foo")) + + expect(NSString(string: "foobar").description).to(beginWith("foo")) + expect(NSString(string: "foobar").description).toNot(beginWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(beginWith("a")) + expect(NSArray(array: ["a", "b"])).toNot(beginWith("b")) +#endif + } + + func testNegativeMatches() { + failsWithErrorMessageForNil("expected to begin with , got ") { + expect(nil as NSArray?).to(beginWith(NSString(string: "b"))) + } + failsWithErrorMessageForNil("expected to not begin with , got ") { + expect(nil as NSArray?).toNot(beginWith(NSString(string: "b"))) + } + + failsWithErrorMessage("expected to begin with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(beginWith(2)) + } + failsWithErrorMessage("expected to not begin with <1>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(beginWith(1)) + } + failsWithErrorMessage("expected to begin with , got ") { + expect("batman").to(beginWith("atm")) + } + failsWithErrorMessage("expected to not begin with , got ") { + expect("batman").toNot(beginWith("bat")) + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift @@ -0,0 +1,86 @@ +import Foundation +import XCTest +import Nimble + +final class ContainElementSatisfyingTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainElementSatisfyingTest) -> () throws -> Void)] { + return [ + ("testContainElementSatisfying", testContainElementSatisfying), + ("testContainElementSatisfyingDefaultErrorMessage", testContainElementSatisfyingDefaultErrorMessage), + ("testContainElementSatisfyingSpecificErrorMessage", testContainElementSatisfyingSpecificErrorMessage), + ("testContainElementSatisfyingNegativeCase", + testContainElementSatisfyingNegativeCase), + ("testContainElementSatisfyingNegativeCaseDefaultErrorMessage", + testContainElementSatisfyingNegativeCaseDefaultErrorMessage), + ("testContainElementSatisfyingNegativeCaseSpecificErrorMessage", + testContainElementSatisfyingNegativeCaseSpecificErrorMessage), + ] + } + + func testContainElementSatisfying() { + var orderIndifferentArray = [1, 2, 3] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + + orderIndifferentArray = [3, 1, 2] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + } + + func testContainElementSatisfyingDefaultErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + })) + } + } + + func testContainElementSatisfyingSpecificErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection equal to 4") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + }, "equal to 4")) + } + } + + func testContainElementSatisfyingNegativeCase() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "armadillos" + })) + } + + func testContainElementSatisfyingNegativeCaseDefaultErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + })) + } + } + + func testContainElementSatisfyingNegativeCaseSpecificErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection equal to 'kittens'") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + }, "equal to 'kittens'")) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..1d8a1eb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift @@ -0,0 +1,95 @@ +import Foundation +import XCTest +import Nimble + +final class ContainTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainTest) -> () throws -> Void)] { + return [ + ("testContain", testContain), + ("testContainSubstring", testContainSubstring), + ("testContainObjCSubstring", testContainObjCSubstring), + ("testVariadicArguments", testVariadicArguments), + ("testCollectionArguments", testCollectionArguments), + ] + } + + func testContain() { + expect([1, 2, 3]).to(contain(1)) + expect([1, 2, 3] as [CInt]).to(contain(1 as CInt)) + expect([1, 2, 3] as [CInt]).toNot(contain(4 as CInt)) + expect(["foo", "bar", "baz"]).to(contain("baz")) + expect([1, 2, 3]).toNot(contain(4)) + expect(["foo", "bar", "baz"]).toNot(contain("ba")) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a"])).to(contain(NSString(string: "a"))) + expect(NSArray(array: ["a"])).toNot(contain(NSString(string: "b"))) + expect(NSArray(object: 1) as NSArray?).to(contain(1)) +#endif + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b")) + } + + failsWithErrorMessageForNil("expected to contain , got ") { + expect(nil as [String]?).to(contain("bar")) + } + failsWithErrorMessageForNil("expected to not contain , got ") { + expect(nil as [String]?).toNot(contain("b")) + } + } + + func testContainSubstring() { + expect("foo").to(contain("o")) + expect("foo").to(contain("oo")) + expect("foo").toNot(contain("z")) + expect("foo").toNot(contain("zz")) + + failsWithErrorMessage("expected to contain , got ") { + expect("foo").to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got ") { + expect("foo").toNot(contain("oo")) + } + } + + func testContainObjCSubstring() { + let str = NSString(string: "foo") + expect(str).to(contain(NSString(string: "o"))) + expect(str).to(contain(NSString(string: "oo"))) + expect(str).toNot(contain(NSString(string: "z"))) + expect(str).toNot(contain(NSString(string: "zz"))) + } + + func testVariadicArguments() { + expect([1, 2, 3]).to(contain(1, 2)) + expect([1, 2, 3]).toNot(contain(1, 4)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("a", "bar")) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b", "a")) + } + } + + func testCollectionArguments() { + expect([1, 2, 3]).to(contain([1, 2])) + expect([1, 2, 3]).toNot(contain([1, 4])) + + let collection = Array(1...10) + let slice = Array(collection[3...5]) + expect(collection).to(contain(slice)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain(["a", "bar"])) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain(["b", "a"])) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..30e3b26 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift @@ -0,0 +1,56 @@ +import Foundation +import XCTest +import Nimble + +final class EndWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EndWithTest) -> () throws -> Void)] { + return [ + ("testEndWithPositives", testEndWithPositives), + ("testEndWithNegatives", testEndWithNegatives), + ] + } + + func testEndWithPositives() { + expect([1, 2, 3]).to(endWith(3)) + expect([1, 2, 3]).toNot(endWith(2)) + expect([]).toNot(endWith(1)) + expect(["a", "b", "a"]).to(endWith("a")) + + expect("foobar").to(endWith("bar")) + expect("foobar").toNot(endWith("oo")) + expect("foobarfoo").to(endWith("foo")) + + expect(NSString(string: "foobar").description).to(endWith("bar")) + expect(NSString(string: "foobar").description).toNot(endWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(endWith("b")) + expect(NSArray(array: ["a", "b"])).toNot(endWith("a")) + expect(NSArray(array: [])).toNot(endWith("a")) + expect(NSArray(array: ["a", "b", "a"])).to(endWith("a")) +#endif + } + + func testEndWithNegatives() { + failsWithErrorMessageForNil("expected to end with <2>, got ") { + expect(nil as [Int]?).to(endWith(2)) + } + failsWithErrorMessageForNil("expected to not end with <2>, got ") { + expect(nil as [Int]?).toNot(endWith(2)) + } + + failsWithErrorMessage("expected to end with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(endWith(2)) + } + failsWithErrorMessage("expected to not end with <3>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(endWith(3)) + } + failsWithErrorMessage("expected to end with , got ") { + expect("batman").to(endWith("atm")) + } + failsWithErrorMessage("expected to not end with , got ") { + expect("batman").toNot(endWith("man")) + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..85be751 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift @@ -0,0 +1,276 @@ +import Foundation +import XCTest +import Nimble + +final class EqualTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EqualTest) -> () throws -> Void)] { + return [ + ("testEquality", testEquality), + ("testArrayEquality", testArrayEquality), + ("testSetEquality", testSetEquality), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ("testDictionaryEquality", testDictionaryEquality), + ("testDataEquality", testDataEquality), + ("testNSObjectEquality", testNSObjectEquality), + ("testOperatorEquality", testOperatorEquality), + ("testOperatorEqualityWithArrays", testOperatorEqualityWithArrays), + ("testOperatorEqualityWithDictionaries", testOperatorEqualityWithDictionaries), + ("testOptionalEquality", testOptionalEquality), + ("testArrayOfOptionalsEquality", testArrayOfOptionalsEquality), + ("testDictionariesWithDifferentSequences", testDictionariesWithDifferentSequences), + ] + } + + func testEquality() { + expect(1 as CInt).to(equal(1 as CInt)) + expect(1 as CInt).to(equal(1)) + expect(1).to(equal(1)) + expect("hello").to(equal("hello")) + expect("hello").toNot(equal("world")) + + expect { + 1 + }.to(equal(1)) + + failsWithErrorMessage("expected to equal , got ") { + expect("hello").to(equal("world")) + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello").toNot(equal("hello")) + } + } + + func testArrayEquality() { + expect([1, 2, 3]).to(equal([1, 2, 3])) + expect([1, 2, 3]).toNot(equal([1, 2])) + expect([1, 2, 3]).toNot(equal([1, 2, 4])) + + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + expect(array1).to(equal(array2)) + expect(array1).to(equal([1, 2, 3])) + expect(array1).toNot(equal([1, 2] as [Int])) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: [1, 2, 3])).to(equal(NSArray(array: [1, 2, 3]))) +#endif + + failsWithErrorMessage("expected to equal <[1, 2]>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(equal([1, 2])) + } + } + + func testSetEquality() { + expect(Set([1, 2])).to(equal(Set([1, 2]))) + expect(Set()).to(equal(Set())) + expect(Set()) == Set() + expect(Set([1, 2])) != Set() + + failsWithErrorMessageForNil("expected to equal <[1, 2]>, got ") { + expect(nil as Set?).to(equal(Set([1, 2]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3]>, missing <[1]>") { + expect(Set([2, 3])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[1, 2, 3, 4]>, extra <[4]>") { + expect(Set([1, 2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])) == Set([1, 2, 3]) + } + + failsWithErrorMessage("expected to not equal <[1, 2, 3]>, got <[1, 2, 3]>") { + expect(Set([1, 2, 3])) != Set([1, 2, 3]) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as String?).to(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect("foo").toNot(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect(nil as String?).toNot(equal("bar")) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int]?).to(equal(nil as [Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1]>, got ") { + expect(nil as [Int]?).toNot(equal([1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1]>") { + expect([1]).toNot(equal(nil as [Int]?)) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int: Int]?).to(equal(nil as [Int: Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1: 1]>, got ") { + expect(nil as [Int: Int]?).toNot(equal([1: 1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1: 1]>") { + expect([1: 1]).toNot(equal(nil as [Int: Int]?)) + } + + failsWithErrorMessageForNil("expected to not equal , got <1>") { + expect(1).toNot(equal(nil)) + } + } + + func testDictionaryEquality() { + expect(["foo": "bar"]).to(equal(["foo": "bar"])) + expect(["foo": "bar"]).toNot(equal(["foo": "baz"])) + + let actual = ["foo": "bar"] + let expected = ["foo": "bar"] + let unexpected = ["foo": "baz"] + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString)).to(equal(["foo": "bar"])) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString) as? [String: String]).to(equal(expected)) +#endif + } + + func testDataEquality() { + let actual = "foobar".data(using: .utf8) + let expected = "foobar".data(using: .utf8) + let unexpected = "foobarfoo".data(using: .utf8) + + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11) + let expectedErrorMessage = "expected to equal >, got >" + #else + let expectedErrorMessage = "expected to equal >," + + " got >" + #endif + + failsWithErrorMessage(expectedErrorMessage) { + expect(actual).to(equal(unexpected)) + } + } + + func testNSObjectEquality() { + expect(NSNumber(value: 1)).to(equal(NSNumber(value: 1))) + expect(NSNumber(value: 1)) == NSNumber(value: 1) + expect(NSNumber(value: 1)) != NSNumber(value: 2) + expect { NSNumber(value: 1) }.to(equal(1)) + } + + func testOperatorEquality() { + expect("foo") == "foo" + expect("foo") != "bar" + + failsWithErrorMessage("expected to equal , got ") { + expect("hello") == "world" + return + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello") != "hello" + return + } + } + + func testOperatorEqualityWithArrays() { + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + let array3: [Int] = [1, 2] + expect(array1) == array2 + expect(array1) != array3 + } + + func testOperatorEqualityWithDictionaries() { + let dict1 = ["foo": "bar"] + let dict2 = ["foo": "bar"] + let dict3 = ["foo": "baz"] + expect(dict1) == dict2 + expect(dict1) != dict3 + } + + func testOptionalEquality() { + expect(1 as CInt?).to(equal(1)) + expect(1 as CInt?).to(equal(1 as CInt?)) + } + + func testArrayOfOptionalsEquality() { + let array1: [Int?] = [1, nil, 3] + let array2: [Int?] = [nil, 2, 3] + let array3: [Int?] = [1, nil, 3] + + expect(array1).toNot(equal(array2)) + expect(array1).to(equal(array3)) + expect(array2).toNot(equal(array3)) + + let allNils1: [String?] = [nil, nil, nil, nil] + let allNils2: [String?] = [nil, nil, nil, nil] + let notReallyAllNils: [String?] = [nil, nil, nil, "turtles"] + + expect(allNils1).to(equal(allNils2)) + expect(allNils1).toNot(equal(notReallyAllNils)) + + let noNils1: [Int?] = [1, 2, 3, 4, 5] + let noNils2: [Int?] = [1, 3, 5, 7, 9] + + expect(noNils1).toNot(equal(noNils2)) + + failsWithErrorMessage("expected to equal <[Optional(1), nil]>, got <[nil, Optional(2)]>") { + let arrayOfOptionalInts: [Int?] = [nil, 2] + let anotherArrayOfOptionalInts: [Int?] = [1, nil] + expect(arrayOfOptionalInts).to(equal(anotherArrayOfOptionalInts)) + return + } + } + + func testDictionariesWithDifferentSequences() { + // see: https://github.com/Quick/Nimble/issues/61 + // these dictionaries generate different orderings of sequences. + let result = ["how": 1, "think": 1, "didnt": 2, "because": 1, + "interesting": 1, "always": 1, "right": 1, "such": 1, + "to": 3, "say": 1, "cool": 1, "you": 1, + "weather": 3, "be": 1, "went": 1, "was": 2, + "sometimes": 1, "and": 3, "mind": 1, "rain": 1, + "whole": 1, "everything": 1, "weather.": 1, "down": 1, + "kind": 1, "mood.": 1, "it": 2, "everyday": 1, "might": 1, + "more": 1, "have": 2, "person": 1, "could": 1, "tenth": 2, + "night": 1, "write": 1, "Youd": 1, "affects": 1, "of": 3, + "Who": 1, "us": 1, "an": 1, "I": 4, "my": 1, "much": 2, + "wrong.": 1, "peacefully.": 1, "amazing": 3, "would": 4, + "just": 1, "grade.": 1, "Its": 2, "The": 2, "had": 1, "that": 1, + "the": 5, "best": 1, "but": 1, "essay": 1, "for": 1, "summer": 2, + "your": 1, "grade": 1, "vary": 1, "pretty": 1, "at": 1, "rain.": 1, + "about": 1, "allow": 1, "thought": 1, "in": 1, "sleep": 1, "a": 1, + "hot": 1, "really": 1, "beach": 1, "life.": 1, "we": 1, "although": 1, ] + + let storyCount = ["The": 2, "summer": 2, "of": 3, "tenth": 2, "grade": 1, + "was": 2, "the": 5, "best": 1, "my": 1, "life.": 1, "I": 4, + "went": 1, "to": 3, "beach": 1, "everyday": 1, "and": 3, + "we": 1, "had": 1, "amazing": 3, "weather.": 1, "weather": 3, + "didnt": 2, "really": 1, "vary": 1, "much": 2, "always": 1, + "pretty": 1, "hot": 1, "although": 1, "sometimes": 1, "at": 1, + "night": 1, "it": 2, "would": 4, "rain.": 1, "mind": 1, "rain": 1, + "because": 1, "cool": 1, "everything": 1, "down": 1, "allow": 1, + "us": 1, "sleep": 1, "peacefully.": 1, "Its": 2, "how": 1, + "affects": 1, "your": 1, "mood.": 1, "Who": 1, "have": 2, + "thought": 1, "that": 1, "could": 1, "write": 1, "a": 1, + "whole": 1, "essay": 1, "just": 1, "about": 1, "in": 1, + "grade.": 1, "kind": 1, "right": 1, "Youd": 1, "think": 1, + "for": 1, "such": 1, "an": 1, "interesting": 1, "person": 1, + "might": 1, "more": 1, "say": 1, "but": 1, "you": 1, "be": 1, "wrong.": 1, ] + + expect(result).to(equal(storyCount)) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble + +final class HaveCountTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (HaveCountTest) -> () throws -> Void)] { + return [ + ("testHaveCountForArray", testHaveCountForArray), + ("testHaveCountForDictionary", testHaveCountForDictionary), + ("testHaveCountForSet", testHaveCountForSet), + ] + } + + func testHaveCountForArray() { + expect([1, 2, 3]).to(haveCount(3)) + expect([1, 2, 3]).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Array with count 1, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Array with count 3, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).notTo(haveCount(3)) + } + } + + func testHaveCountForDictionary() { + let dictionary = ["1": 1, "2": 2, "3": 3] + expect(dictionary).to(haveCount(3)) + expect(dictionary).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Dictionary with count 1, got 3\nActual Value: \(stringify(dictionary))") { + expect(dictionary).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Dictionary with count 3, got 3" + + "\nActual Value: \(stringify(dictionary))") { + expect(dictionary).notTo(haveCount(3)) + } + } + + func testHaveCountForSet() { + let set = Set([1, 2, 3]) + expect(set).to(haveCount(3)) + expect(set).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Set with count 1, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Set with count 3, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).notTo(haveCount(3)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..2d626f2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift @@ -0,0 +1,84 @@ +import Foundation +import XCTest +import Nimble + +final class MatchErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchErrorTest) -> () throws -> Void)] { + return [ + ("testMatchErrorPositive", testMatchErrorPositive), + ("testMatchErrorNegative", testMatchErrorNegative), + ("testMatchNSErrorPositive", testMatchNSErrorPositive), + ("testMatchNSErrorNegative", testMatchNSErrorNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ] + } + + func testMatchErrorPositive() { + expect(NimbleError.laugh).to(matchError(NimbleError.laugh)) + expect(NimbleError.laugh).to(matchError(NimbleError.self)) + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 1))) + + expect(NimbleError.laugh as Error).to(matchError(NimbleError.laugh)) + } + + func testMatchErrorNegative() { + expect(NimbleError.laugh).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh as Error).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh).toNot(matchError(EquatableError.self)) + expect(EquatableError.parameterized(x: 1)).toNot(matchError(EquatableError.parameterized(x: 2))) + } + + func testMatchNSErrorPositive() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 0, userInfo: nil) + + expect(error1).to(matchError(error2)) + } + + func testMatchNSErrorNegative() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + + expect(error1).toNot(matchError(error2)) + } + + func testMatchPositiveMessage() { + failsWithErrorMessage("expected to match error , got ") { + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 2))) + } + failsWithErrorMessage("expected to match error , got ") { + expect(NimbleError.laugh).to(matchError(NimbleError.cry)) + } + failsWithErrorMessage("expected to match error , got ") { + expect(CustomDebugStringConvertibleError.a).to(matchError(CustomDebugStringConvertibleError.b)) + } + + failsWithErrorMessage("expected to match error , got ") { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + expect(error1).to(matchError(error2)) + } + } + + func testMatchNegativeMessage() { + failsWithErrorMessage("expected to not match error , got ") { + expect(NimbleError.laugh).toNot(matchError(NimbleError.laugh)) + } + + failsWithErrorMessage("expected to match error from type , got ") { + expect(NimbleError.laugh).to(matchError(EquatableError.self)) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to match error , got no error") { + expect(nil as Error?).to(matchError(NimbleError.laugh)) + } + + failsWithErrorMessageForNil("expected to not match error , got no error") { + expect(nil as Error?).toNot(matchError(NimbleError.laugh)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift @@ -0,0 +1,46 @@ +import XCTest +import Nimble + +final class MatchTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchTest) -> () throws -> Void)] { + return [ + ("testMatchPositive", testMatchPositive), + ("testMatchNegative", testMatchNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testMatchNils", testMatchNils), + ] + } + + func testMatchPositive() { + expect("11:14").to(match("\\d{2}:\\d{2}")) + } + + func testMatchNegative() { + expect("hello").toNot(match("\\d{2}:\\d{2}")) + } + + func testMatchPositiveMessage() { + let message = "expected to match <\\d{2}:\\d{2}>, got " + failsWithErrorMessage(message) { + expect("hello").to(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNegativeMessage() { + let message = "expected to not match <\\d{2}:\\d{2}>, got <11:14>" + failsWithErrorMessage(message) { + expect("11:14").toNot(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNils() { + failsWithErrorMessageForNil("expected to match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).to(match("\\d{2}:\\d{2}")) + } + + failsWithErrorMessageForNil("expected to not match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).toNot(match("\\d{2}:\\d{2}")) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..ac7f9ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift @@ -0,0 +1,91 @@ +import XCTest +import Nimble +import Foundation + +final class PostNotificationTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PostNotificationTest) -> () throws -> Void)] { + return [ + ("testPassesWhenNoNotificationsArePosted", testPassesWhenNoNotificationsArePosted), + ("testPassesWhenExpectedNotificationIsPosted", testPassesWhenExpectedNotificationIsPosted), + ("testPassesWhenAllExpectedNotificationsArePosted", testPassesWhenAllExpectedNotificationsArePosted), + ("testFailsWhenNoNotificationsArePosted", testFailsWhenNoNotificationsArePosted), + ("testFailsWhenNotificationWithWrongNameIsPosted", testFailsWhenNotificationWithWrongNameIsPosted), + ("testFailsWhenNotificationWithWrongObjectIsPosted", testFailsWhenNotificationWithWrongObjectIsPosted), + ("testPassesWhenExpectedNotificationEventuallyIsPosted", testPassesWhenExpectedNotificationEventuallyIsPosted), + ] + } + + let notificationCenter = NotificationCenter() + + func testPassesWhenNoNotificationsArePosted() { + expect { + // no notifications here! + return nil + }.to(postNotifications(beEmpty(), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenExpectedNotificationIsPosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + self.notificationCenter.post(testNotification) + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenAllExpectedNotificationsArePosted() { + let foo = NSNumber(value: 1) + let bar = NSNumber(value: 2) + let n1 = Notification(name: Notification.Name("Foo"), object: foo) + let n2 = Notification(name: Notification.Name("Bar"), object: bar) + expect { + self.notificationCenter.post(n1) + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1, n2]), fromNotificationCenter: notificationCenter)) + } + + func testFailsWhenNoNotificationsArePosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + failsWithErrorMessage("expected to equal <[\(testNotification)]>, got no notifications") { + expect { + // no notifications here! + return nil + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongNameIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: Notification.Name(n1.name.rawValue + "a"), object: nil) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongObjectIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: n1.name, object: NSObject()) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testPassesWhenExpectedNotificationEventuallyIsPosted() { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + deferToMainQueue { + self.notificationCenter.post(testNotification) + } + return nil + }.toEventually(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + #else + print("\(#function) is missing because toEventually is not implement on this platform") + #endif + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..f62f633 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class RaisesExceptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (RaisesExceptionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testNegativeMatchesDoNotCallClosureWithoutException", testNegativeMatchesDoNotCallClosureWithoutException), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + var anException = NSException(name: NSExceptionName("laugh"), reason: "Lulz", userInfo: ["key": "value"]) + + func testPositiveMatches() { + expect { self.anException.raise() }.to(raiseException()) + expect { self.anException.raise() }.to(raiseException(named: "laugh")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + + func testPositiveMatchesWithClosures() { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName("laugh"))) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("df")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + failsWithErrorMessage("expected to raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "foo")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "bar")) + } + + failsWithErrorMessage( + "expected to raise exception with name with reason with userInfo <{k = v;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["k": "v"])) + } + + failsWithErrorMessage("expected to raise any exception, got no exception") { + expect { self.anException }.to(raiseException()) + } + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + failsWithErrorMessage("expected to raise exception with name with reason , got no exception") { + expect { self.anException }.to(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "bar", reason: "Lulz")) + } + failsWithErrorMessage("expected to not raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh")) + } + failsWithErrorMessage("expected to not raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to not raise exception with name with reason with userInfo <{key = value;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutException() { + failsWithErrorMessage("expected to raise exception that satisfies block, got no exception") { + expect { self.anException }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName(rawValue: "foo"))) + }) + } + + failsWithErrorMessage("expected to raise exception with name that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "ha") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason with userInfo <{}> that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + } + + func testNegativeMatchesWithClosure() { + failsWithErrorMessage("expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + let innerFailureMessage = "expected to begin with , got " + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "wrong") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift new file mode 100644 index 0000000..42ed892 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift @@ -0,0 +1,57 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAllOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAllOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAllOf", testSatisfyAllOf), + ("testOperatorAnd", testOperatorAnd), + ] + } + + func testSatisfyAllOf() { + expect(2).to(satisfyAllOf(equal(2), beLessThan(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAllOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAllOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAllOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").to(satisfyAllOf(contain("e"), beginWith("tur"))) + expect(82.0).to(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(82.00001))) + expect(false).toNot(satisfyAllOf(beTrue(), beFalse())) + expect(true).toNot(satisfyAllOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2") { + expect(2).to(satisfyAllOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match all of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, and {equal <[5, 6, 7]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAllOf(allPass("be less than 4", {$0 < 4}), equal([5, 6, 7]))) + } + failsWithErrorMessage( + "expected to not match all of: {be false}, got false") { + expect(false).toNot(satisfyAllOf(beFalse())) + } + failsWithErrorMessage( + "expected to not match all of: {be greater than <10.5>}, and {be less than <100.75>}, and {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorAnd() { + expect(2).to(equal(2) && beLessThan(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).to(beLessThan(3) && beGreaterThan(1)) +#else + expect(2 as NSNumber).to(beLessThan(3 as NSNumber) && beGreaterThan(1 as NSNumber)) +#endif + expect("turtle").to(contain("t") && endWith("tle")) + expect(82.0).to(beGreaterThan(10.5) && beLessThan(100.75)) + expect(false).to(beFalsy() && beFalse()) + expect(false).toNot(beTrue() && beFalse()) + expect(true).toNot(beTruthy() && beFalsy()) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAnyOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAnyOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAnyOf", testSatisfyAnyOf), + ("testOperatorOr", testOperatorOr), + ] + } + + func testSatisfyAnyOf() { + expect(2).to(satisfyAnyOf(equal(2), equal(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAnyOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAnyOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAnyOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").toNot(satisfyAnyOf(contain("a"), endWith("magic"))) + expect(82.0).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + expect(false).to(satisfyAnyOf(beTrue(), beFalse())) + expect(true).to(satisfyAnyOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2") { + expect(2).to(satisfyAnyOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match one of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, or {equal <[1, 2, 3, 4]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAnyOf(allPass("be less than 4", {$0 < 4}), equal([1, 2, 3, 4]))) + } + failsWithErrorMessage( + "expected to match one of: {be true}, got false") { + expect(false).to(satisfyAnyOf(beTrue())) + } + failsWithErrorMessage( + "expected to not match one of: {be less than <10.5>}, or {be greater than <100.75>}, or {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorOr() { + expect(2).to(equal(2) || equal(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(equal(3) || equal("turtles")) +#else + expect(2 as NSNumber).toNot(equal(3 as NSNumber) || equal("turtles" as NSString)) +#endif + expect("turtle").toNot(contain("a") || endWith("magic")) + expect(82.0).toNot(beLessThan(10.5) || beGreaterThan(100.75)) + expect(false).to(beTrue() || beFalse()) + expect(true).to(beTruthy() || beFalsy()) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..68086e0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,62 @@ +import Foundation +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class ThrowAssertionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowAssertionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testErrorThrown", testErrorThrown), + ("testPostAssertionCodeNotRun", testPostAssertionCodeNotRun), + ("testNegativeMatch", testNegativeMatch), + ("testPositiveMessage", testPositiveMessage), + ("testNegativeMessage", testNegativeMessage), + ] + } + + func testPositiveMatch() { + expect { () -> Void in fatalError() }.to(throwAssertion()) + } + + func testErrorThrown() { + expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + } + + func testPostAssertionCodeNotRun() { + var reachedPoint1 = false + var reachedPoint2 = false + + expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true + }.to(throwAssertion()) + + expect(reachedPoint1) == true + expect(reachedPoint2) == false + } + + func testNegativeMatch() { + var reachedPoint1 = false + + expect { reachedPoint1 = true }.toNot(throwAssertion()) + + expect(reachedPoint1) == true + } + + func testPositiveMessage() { + failsWithErrorMessage("expected to throw an assertion") { + expect { () -> Void? in return }.to(throwAssertion()) + } + } + + func testNegativeMessage() { + failsWithErrorMessage("expected to not throw an assertion") { + expect { () -> Void in fatalError() }.toNot(throwAssertion()) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..f11c8c5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift @@ -0,0 +1,155 @@ +import XCTest +import Nimble + +enum NimbleError: Error { + case laugh + case cry +} + +enum EquatableError: Error { + case parameterized(x: Int) +} + +extension EquatableError: Equatable { +} + +func == (lhs: EquatableError, rhs: EquatableError) -> Bool { + switch (lhs, rhs) { + case (.parameterized(let l), .parameterized(let r)): + return l == r + } +} + +enum CustomDebugStringConvertibleError: Error { + case a + case b +} + +extension CustomDebugStringConvertibleError: CustomDebugStringConvertible { + var debugDescription: String { + return "code=\(_code)" + } +} + +final class ThrowErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowErrorTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testPositiveNegatedMatches", testPositiveNegatedMatches), + ("testNegativeNegatedMatches", testNegativeNegatedMatches), + ("testNegativeMatchesDoNotCallClosureWithoutError", testNegativeMatchesDoNotCallClosureWithoutError), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + func testPositiveMatches() { + expect { throw NimbleError.laugh }.to(throwError()) + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh)) + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self)) + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 1))) + expect { throw EquatableError.parameterized(x: 1) }.toNot(throwError(EquatableError.parameterized(x: 2))) + } + + func testPositiveMatchesWithClosures() { + // Generic typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { error in + guard case EquatableError.parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Explicit typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { (error: EquatableError) in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over errorType argument + expect { throw EquatableError.parameterized(x: 42) }.to(throwError(errorType: EquatableError.self) { error in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).to(beginWith("Nim")) + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Different case + failsWithErrorMessage("expected to throw error , got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry)) + } + // Different case with closure + failsWithErrorMessage("expected to throw error that satisfies block, got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry) { _ in return }) + } + // Different case, implementing CustomDebugStringConvertible + failsWithErrorMessage("expected to throw error , got ") { + expect { throw CustomDebugStringConvertibleError.a }.to(throwError(CustomDebugStringConvertibleError.b)) + } + } + + func testPositiveNegatedMatches() { + // No error at all + expect { return }.toNot(throwError()) + // Different case + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.cry)) + } + + func testNegativeNegatedMatches() { + // No error at all + failsWithErrorMessage("expected to not throw any error, got ") { + expect { throw NimbleError.laugh }.toNot(throwError()) + } + // Different error + failsWithErrorMessage("expected to not throw error , got ") { + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.laugh)) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutError() { + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError { _ in + fail() + }) + } + + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError(NimbleError.laugh) { _ in + fail() + }) + } + } + + func testNegativeMatchesWithClosure() { + let moduleName = "NimbleTests" + let innerFailureMessage = "expected to equal , got <\(moduleName).NimbleError>" + let closure = { (error: Error) in + expect(error._domain).to(equal("foo")) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error from type that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self, closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh, closure: closure)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift new file mode 100644 index 0000000..dde999a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift @@ -0,0 +1,36 @@ +import XCTest +import Nimble + +final class ToSucceedTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ToSucceedTest) -> () throws -> Void)] { + return [ + ("testToSucceed", testToSucceed), + ] + } + + func testToSucceed() { + expect({ + return .succeeded + }).to(succeed()) + + expect({ + return .failed(reason: "") + }).toNot(succeed()) + + failsWithErrorMessageForNil("expected a closure, got ") { + expect(nil as (() -> ToSucceedResult)?).to(succeed()) + } + + failsWithErrorMessage("expected to succeed, got because ") { + expect({ + .failed(reason: "something went wrong") + }).to(succeed()) + } + + failsWithErrorMessage("expected to not succeed, got ") { + expect({ + return .succeeded + }).toNot(succeed()) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift new file mode 100644 index 0000000..ce8181b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift @@ -0,0 +1,128 @@ +import Foundation +import XCTest +import Nimble + +final class SynchronousTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SynchronousTest) -> () throws -> Void)] { + return [ + ("testFailAlwaysFails", testFailAlwaysFails), + ("testUnexpectedErrorsThrownFails", testUnexpectedErrorsThrownFails), + ("testToMatchesIfMatcherReturnsTrue", testToMatchesIfMatcherReturnsTrue), + ("testToProvidesActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToMatchAgainstLazyProperties", testToMatchAgainstLazyProperties), + ("testToNotMatchesIfMatcherReturnsTrue", testToNotMatchesIfMatcherReturnsTrue), + ("testToNotProvidesActualValueExpression", testToNotProvidesActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpression", testToNotProvidesAMemoizedActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToNotNegativeMatches", testToNotNegativeMatches), + ("testNotToMatchesLikeToNot", testNotToMatchesLikeToNot), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testFailAlwaysFails() { + failsWithErrorMessage("My error message") { + fail("My error message") + } + failsWithErrorMessage("fail() always fails") { + fail() + } + } + + func testUnexpectedErrorsThrownFails() { + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.to(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toNot(equal(1)) + } + } + + func testToMatchesIfMatcherReturnsTrue() { + expect(1).to(MatcherFunc { _, _ in true }) + expect {1}.to(MatcherFunc { _, _ in true }) + } + + func testToProvidesActualValueExpression() { + var value: Int? + expect(1).to(MatcherFunc { expr, _ in value = try expr.evaluate(); return true }) + expect(value).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToMatchAgainstLazyProperties() { + expect(ObjectWithLazyProperty().value).to(equal("hello")) + expect(ObjectWithLazyProperty().value).toNot(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).to(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).toNot(equal("hello")) + } + + // repeated tests from to() for toNot() + func testToNotMatchesIfMatcherReturnsTrue() { + expect(1).toNot(MatcherFunc { _, _ in false }) + expect {1}.toNot(MatcherFunc { _, _ in false }) + } + + func testToNotProvidesActualValueExpression() { + var value: Int? + expect(1).toNot(MatcherFunc { expr, _ in value = try expr.evaluate(); return false }) + expect(value).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotNegativeMatches() { + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }) + } + } + + func testNotToMatchesLikeToNot() { + expect(1).notTo(MatcherFunc { _, _ in false }) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift @@ -0,0 +1,64 @@ +import XCTest +import Nimble + +final class UserDescriptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (UserDescriptionTest) -> () throws -> Void)] { + return [ + ("testToMatcher_CustomFailureMessage", testToMatcher_CustomFailureMessage), + ("testNotToMatcher_CustomFailureMessage", testNotToMatcher_CustomFailureMessage), + ("testToNotMatcher_CustomFailureMessage", testToNotMatcher_CustomFailureMessage), + ("testToEventuallyMatch_CustomFailureMessage", testToEventuallyMatch_CustomFailureMessage), + ("testToEventuallyNotMatch_CustomFailureMessage", testToEventuallyNotMatch_CustomFailureMessage), + ("testToNotEventuallyMatch_CustomFailureMessage", testToNotEventuallyMatch_CustomFailureMessage), + ] + } + + func testToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }, description: "These aren't equal!") + } + } + + func testNotToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).notTo(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToNotMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't eventually equal!\n" + + "expected to eventually equal <1>, got <0>") { + expect { 0 }.toEventually(equal(1), description: "These aren't eventually equal!") + } + } + + func testToEventuallyNotMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + + func testToNotEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h @@ -0,0 +1,15 @@ +@import Nimble; +#import "NimbleTests-Swift.h" + +// Use this when you want to verify the failure message for when an expectation fails +#define expectFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessage:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + +#define expectFailureMessages(MSGS, BLOCK) \ +[NimbleHelper expectFailureMessages:(MSGS) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + + +// Use this when you want to verify the failure message with the nil message postfixed +// to it: " (use beNil() to match nils)" +#define expectNilFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessageForNil:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..4bdc021 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m @@ -0,0 +1,38 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAllPassTest : XCTestCase + +@end + +@implementation ObjCAllPassTest + +- (void)testPositiveMatches { + expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); + expect(@[@1, @2, @3,@4]).toNot(allPass(beGreaterThan(@5))); + + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).to(allPass(beLessThan(@5))); + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).toNot(allPass(beGreaterThan(@5))); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to all be less than <3>, but failed first at element" + " <3> in <[1, 2, 3, 4]>", ^{ + expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@3))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect(@[@1, @2, @3, @4]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect([NSSet setWithArray:@[@1, @2, @3, @4]]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).to(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).toNot(allPass(beLessThan(@5))); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m @@ -0,0 +1,55 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAsyncTest : XCTestCase + +@end + +@implementation ObjCAsyncTest + +- (void)testAsync { + __block id obj = @1; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = nil; + }); + expect(obj).toEventually(beNil()); +} + + +- (void)testAsyncWithCustomTimeout { + __block id obj = nil; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = @1; + }); + expect(obj).withTimeout(5).toEventuallyNot(beNil()); +} + +- (void)testAsyncCallback { + waitUntil(^(void (^done)(void)){ + done(); + }); + + expectFailureMessage(@"Waited more than 1.0 second", ^{ + waitUntil(^(void (^done)(void)){ /* ... */ }); + }); + + expectFailureMessage(@"Waited more than 0.01 seconds", ^{ + waitUntilTimeout(0.01, ^(void (^done)(void)){ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [NSThread sleepForTimeInterval:0.1]; + done(); + }); + }); + }); + + expectFailureMessage(@"expected to equal , got ", ^{ + waitUntil(^(void (^done)(void)){ + [NSThread sleepForTimeInterval:0.1]; + expect(@"hello").to(equal(@"goodbye")); + done(); + }); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeAnInstanceOfTest : XCTestCase +@end + +@implementation ObjCBeAnInstanceOfTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beAnInstanceOf([NSNull class])); + expect(@1).toNot(beAnInstanceOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be an instance of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAnInstanceOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAnInstanceOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be an instance of NSNull, got ", ^{ + expect(nil).to(beAnInstanceOf([NSNull class])); + }); + + expectNilFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect(nil).toNot(beAnInstanceOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeCloseToTest : XCTestCase + +@end + +@implementation ObjCBeCloseToTest + +- (void)testPositiveMatches { + expect(@1.2).to(beCloseTo(@1.2001)); + expect(@1.2).to(beCloseTo(@2).within(10)); + expect(@2).toNot(beCloseTo(@1)); + expect(@1.00001).toNot(beCloseTo(@1).within(0.00000001)); + + expect(1.2).to(beCloseTo(1.2001)); + expect(1.2).to(beCloseTo(2).within(10)); + expect(2).toNot(beCloseTo(1)); + expect(1.00001).toNot(beCloseTo(1).within(0.00000001)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(@1).to(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(@(0.0001)).toNot(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(1).to(beCloseTo(0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(0.0001).toNot(beCloseTo(0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be close to <0> (within 0.001), got ", ^{ + expect(nil).to(beCloseTo(@0)); + }); + expectNilFailureMessage(@"expected to not be close to <0> (within 0.001), got ", ^{ + expect(nil).toNot(beCloseTo(@0)); + }); +} + + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..5e803cb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m @@ -0,0 +1,89 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeEmptyTest : XCTestCase +@end + +@implementation ObjCBeEmptyTest + +- (void)testPositiveMatches { + expect(@[]).to(beEmpty()); + expect(@"").to(beEmpty()); + expect(@{}).to(beEmpty()); + expect([NSSet set]).to(beEmpty()); + expect([NSIndexSet indexSet]).to(beEmpty()); + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]).to(beEmpty()); + + expect(@[@1, @2]).toNot(beEmpty()); + expect(@"a").toNot(beEmpty()); + expect(@{@"key": @"value"}).toNot(beEmpty()); + expect([NSSet setWithObject:@1]).toNot(beEmpty()); + expect([NSIndexSet indexSetWithIndex:1]).toNot(beEmpty()); + + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + expect(table).toNot(beEmpty()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be empty, got ", ^{ + expect(@"foo").to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect(@[@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{key = value;}>", ^{ + expect(@{@"key": @"value"}).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{(1)}>", ^{ + expect([NSSet setWithObject:@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect([NSIndexSet indexSetWithIndex:1]).to(beEmpty()); + }); + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + NSString *tableString = [[table description] stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be empty, got <%@>", tableString]), ^{ + expect(table).to(beEmpty()); + }); + + expectFailureMessage(@"expected to not be empty, got <>", ^{ + expect(@"").toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect(@[]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{}>", ^{ + expect(@{}).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{()}>", ^{ + expect([NSSet set]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect([NSIndexSet indexSet]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got ", ^{ + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]).toNot(beEmpty()); + }); +} + +- (void)testItDoesNotMatchNil { + expectNilFailureMessage(@"expected to be empty, got ", ^{ + expect(nil).to(beEmpty()); + }); + expectNilFailureMessage(@"expected to not be empty, got ", ^{ + expect(nil).toNot(beEmpty()); + }); +} + +- (void)testItReportsTypesItMatchesAgainst { + expectFailureMessage(@"expected to be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).to(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).toNot(beEmpty()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m @@ -0,0 +1,46 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalseTest : XCTestCase + +@end + +@implementation ObjCBeFalseTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalse()); + expect(@YES).toNot(beFalse()); + + expect(false).to(beFalse()); + expect(true).toNot(beFalse()); + + expect(NO).to(beFalse()); + expect(YES).toNot(beFalse()); + + expect(10).toNot(beFalse()); +} + +- (void)testNegativeMatches { + expectNilFailureMessage(@"expected to be false, got ", ^{ + expect(nil).to(beFalse()); + }); + expectNilFailureMessage(@"expected to not be false, got ", ^{ + expect(nil).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(true).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(false).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(YES).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(NO).toNot(beFalse()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m @@ -0,0 +1,58 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalsyTest : XCTestCase + +@end + +@implementation ObjCBeFalsyTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalsy()); + expect(@YES).toNot(beFalsy()); + expect(nil).to(beFalsy()); + + expect(true).toNot(beFalsy()); + expect(false).to(beFalsy()); + + expect(YES).toNot(beFalsy()); + expect(NO).to(beFalsy()); + + expect(10).toNot(beFalsy()); + expect(0).to(beFalsy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to not be falsy, got ", ^{ + expect(nil).toNot(beFalsy()); + }); + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(@1).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(@NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(true).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(false).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(YES).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <10>", ^{ + expect(10).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(0).toNot(beFalsy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..28862ba --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m @@ -0,0 +1,44 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThanOrEqualTo(@2)); + expect(@2).toNot(beGreaterThanOrEqualTo(@3)); + expect(2).to(beGreaterThanOrEqualTo(0)); + expect(2).to(beGreaterThanOrEqualTo(2)); + expect(2).toNot(beGreaterThanOrEqualTo(3)); + expect(2.5).to(beGreaterThanOrEqualTo(2)); + expect(2.5).to(beGreaterThanOrEqualTo(2.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThanOrEqualTo(@0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThanOrEqualTo(@(1))); + }); + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(-1).to(beGreaterThanOrEqualTo(0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(2).toNot(beGreaterThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than or equal to <-1>, got ", ^{ + expect(nil).to(beGreaterThanOrEqualTo(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than or equal to <1>, got ", ^{ + expect(nil).toNot(beGreaterThanOrEqualTo(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..5a57d54 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThan(@1)); + expect(@2).toNot(beGreaterThan(@2)); + expect(@2).to(beGreaterThan(0)); + expect(@2).toNot(beGreaterThan(2)); + expect(2.5).to(beGreaterThan(1.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThan(@(0))); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThan(@(1))); + }); + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(-1).to(beGreaterThan(0)); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(2).toNot(beGreaterThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than <-1>, got ", ^{ + expect(nil).to(beGreaterThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than <1>, got ", ^{ + expect(nil).toNot(beGreaterThan(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m @@ -0,0 +1,68 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeIdenticalToTest : XCTestCase + +@end + +@implementation ObjCBeIdenticalToTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beIdenticalTo([NSNull null])); + expect(@2).toNot(beIdenticalTo(@3)); +} + +- (void)testNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(beIdenticalTo(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(beIdenticalTo(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testAliasPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(be([NSNull null])); + expect(@2).toNot(be(@3)); +} + +- (void)testAliasNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(be(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(be(obj)); + }); +} + +- (void)testAliasNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(be(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(be(obj)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeKindOfTest : XCTestCase + +@end + +@implementation ObjCBeKindOfTest + +- (void)testPositiveMatches { + NSMutableArray *array = [NSMutableArray array]; + expect(array).to(beAKindOf([NSArray class])); + expect(@1).toNot(beAKindOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be a kind of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAKindOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAKindOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be a kind of NSNull, got ", ^{ + expect(nil).to(beAKindOf([NSNull class])); + }); + expectNilFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect(nil).toNot(beAKindOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m @@ -0,0 +1,43 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeLessThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThanOrEqualTo(@2)); + expect(@2).toNot(beLessThanOrEqualTo(@1)); + expect(2).to(beLessThanOrEqualTo(2)); + expect(2).toNot(beLessThanOrEqualTo(1)); + expect(2).toNot(beLessThanOrEqualTo(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(@2).to(beLessThanOrEqualTo(@1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(@1).toNot(beLessThanOrEqualTo(@1)); + }); + + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(2).to(beLessThanOrEqualTo(1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(1).toNot(beLessThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than or equal to <1>, got ", ^{ + expect(nil).to(beLessThanOrEqualTo(@1)); + }); + expectNilFailureMessage(@"expected to not be less than or equal to <-1>, got ", ^{ + expect(nil).toNot(beLessThanOrEqualTo(@(-1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..9750641 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanTest : XCTestCase + +@end + +@implementation ObjCBeLessThanTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThan(@3)); + expect(@2).toNot(beLessThan(@2)); + expect(2).to(beLessThan(3)); + expect(2).toNot(beLessThan(2)); + expect(2).toNot(beLessThan(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(@(1)).to(beLessThan(@0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(@0).toNot(beLessThan(@1)); + }); + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(1).to(beLessThan(0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(0).toNot(beLessThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than <-1>, got ", ^{ + expect(nil).to(beLessThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be less than <1>, got ", ^{ + expect(nil).toNot(beLessThan(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m @@ -0,0 +1,24 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeNilTest : XCTestCase + +@end + +@implementation ObjCBeNilTest + +- (void)testPositiveMatches { + expect(nil).to(beNil()); + expect(@NO).toNot(beNil()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be nil, got <1>", ^{ + expect(@1).to(beNil()); + }); + expectFailureMessage(@"expected to not be nil, got ", ^{ + expect(nil).toNot(beNil()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTrueTest : XCTestCase + +@end + +@implementation ObjCBeTrueTest + +- (void)testPositiveMatches { + expect(@YES).to(beTrue()); + expect(@NO).toNot(beTrue()); + expect(nil).toNot(beTrue()); + + expect(true).to(beTrue()); + expect(false).toNot(beTrue()); + + expect(YES).to(beTrue()); + expect(NO).toNot(beTrue()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(@NO).to(beTrue()); + }); + expectFailureMessage(@"expected to be true, got ", ^{ + expect(nil).to(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(false).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(true).toNot(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(NO).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(YES).toNot(beTrue()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m @@ -0,0 +1,55 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTruthyTest : XCTestCase + +@end + +@implementation ObjCBeTruthyTest + +- (void)testPositiveMatches { + expect(@YES).to(beTruthy()); + expect(@NO).toNot(beTruthy()); + expect(nil).toNot(beTruthy()); + + expect(true).to(beTruthy()); + expect(false).toNot(beTruthy()); + + expect(YES).to(beTruthy()); + expect(NO).toNot(beTruthy()); + + expect(10).to(beTruthy()); + expect(0).toNot(beTruthy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be truthy, got ", ^{ + expect(nil).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(@1).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(@NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(false).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(true).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(YES).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <10>", ^{ + expect(10).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(0).to(beTruthy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeginWithTest : XCTestCase + +@end + +@implementation ObjCBeginWithTest + +- (void)testPositiveMatches { + expect(@"hello world!").to(beginWith(@"hello")); + expect(@"hello world!").toNot(beginWith(@"world")); + + NSArray *array = @[@1, @2]; + expect(array).to(beginWith(@1)); + expect(array).toNot(beginWith(@2)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to begin with , got ", ^{ + expect(@"foo").to(beginWith(@"bar")); + }); + expectFailureMessage(@"expected to not begin with , got ", ^{ + expect(@"foo").toNot(beginWith(@"foo")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to begin with <1>, got ", ^{ + expect(nil).to(beginWith(@1)); + }); + expectNilFailureMessage(@"expected to not begin with <1>, got ", ^{ + expect(nil).toNot(beginWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m @@ -0,0 +1,64 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainElementSatisfyingTest : XCTestCase + +@end + +@implementation ObjCContainElementSatisfyingTest + +- (void)testPassingMatches { + NSArray *orderIndifferentArray = @[@1, @2, @3]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + orderIndifferentArray = @[@3, @1, @2]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + NSSet *orderIndifferentSet = [NSSet setWithObjects:@"turtle test", @"turtle assessment", nil]; + expect(orderIndifferentSet).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"turtle assessment"]; + })); +} + +- (void)testFailingMatches { + expectFailureMessage(@"expected to find object in collection that satisfies predicate", ^{ + expect(@[@1]).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((nil)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((@3)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); +} + +- (void)testNegativeCases { + NSArray *orderIndifferentArray = @[@"puppies", @"kittens", @"turtles"]; + expect(orderIndifferentArray).toNot(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"armadillos"]; + })); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..8b954fe --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m @@ -0,0 +1,67 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainTest : XCTestCase + +@end + +@implementation ObjCContainTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1)); + expect(array).toNot(contain(@"HI")); + expect(@"String").to(contain(@"Str")); + expect(@"Other").toNot(contain(@"Str")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to contain <3>, got <(1, 2)>", ^{ + expect((@[@1, @2])).to(contain(@3)); + }); + expectFailureMessage(@"expected to not contain <2>, got <(1, 2)>", ^{ + expect((@[@1, @2])).toNot(contain(@2)); + }); + + expectFailureMessage(@"expected to contain , got ", ^{ + expect(@"la").to(contain(@"hi")); + }); + expectFailureMessage(@"expected to not contain , got ", ^{ + expect(@"hihihi").toNot(contain(@"hi")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to contain <3>, got ", ^{ + expect(nil).to(contain(@3)); + }); + expectNilFailureMessage(@"expected to not contain <3>, got ", ^{ + expect(nil).toNot(contain(@3)); + }); + + expectNilFailureMessage(@"expected to contain , got ", ^{ + expect(nil).to(contain(@"hi")); + }); + expectNilFailureMessage(@"expected to not contain , got ", ^{ + expect(nil).toNot(contain(@"hi")); + }); +} + +- (void)testVariadicArguments { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1, @2)); + expect(array).toNot(contain(@"HI", @"whale")); + expect(@"String").to(contain(@"Str", @"ng")); + expect(@"Other").toNot(contain(@"Str", @"Oth")); + + + expectFailureMessage(@"expected to contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).to(contain(@"a", @"bar")); + }); + + expectFailureMessage(@"expected to not contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).toNot(contain(@"a", @"b")); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEndWithTest : XCTestCase + +@end + +@implementation ObjCEndWithTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(@"hello world!").to(endWith(@"world!")); + expect(@"hello world!").toNot(endWith(@"hello")); + expect(array).to(endWith(@2)); + expect(array).toNot(endWith(@1)); + expect(@1).toNot(contain(@"foo")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to end with , got ", ^{ + expect(@"hello world!").to(endWith(@"?")); + }); + expectFailureMessage(@"expected to not end with , got ", ^{ + expect(@"hello world!").toNot(endWith(@"!")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to end with <1>, got ", ^{ + expect(nil).to(endWith(@1)); + }); + expectNilFailureMessage(@"expected to not end with <1>, got ", ^{ + expect(nil).toNot(endWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..9d1361e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m @@ -0,0 +1,94 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEqualTest : XCTestCase + +@end + +@implementation ObjCEqualTest + +- (void)testPositiveMatches { + expect(@1).to(equal(@1)); + expect(@1).toNot(equal(@2)); + expect(@1).notTo(equal(@2)); + expect(@"hello").to(equal(@"hello")); + expect("hello").to(equal("hello")); + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 10))); + expect(NSMakeRange(0, 10)).toNot(equal(NSMakeRange(0, 5))); + expect((NSInteger)1).to(equal((NSInteger)1)); + expect((NSInteger)1).toNot(equal((NSInteger)2)); + expect((NSUInteger)1).to(equal((NSUInteger)1)); + expect((NSUInteger)1).toNot(equal((NSUInteger)2)); + expect(0).to(equal(0)); + expect(1).to(equal(1)); + expect(1).toNot(equal(2)); + expect(1.0).to(equal(1.0)); // Note: not recommended, use beCloseTo() instead + expect(1.0).toNot(equal(2.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).to(equal((float)1.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).toNot(equal((float)2.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).to(equal((double)1.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).toNot(equal((double)2.0)); // Note: not recommended, use beCloseTo() instead + expect((long long)1).to(equal((long long)1)); + expect((long long)1).toNot(equal((long long)2)); + expect((unsigned long long)1).to(equal((unsigned long long)1)); + expect((unsigned long long)1).toNot(equal((unsigned long long)2)); +} + +- (void)testNimbleCurrentlyBoxesNumbersWhichAllowsImplicitTypeConversions { + expect(1).to(equal(1.0)); + expect((long long)1).to(equal((unsigned long long)1)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(@1).to(equal(@2)); + }); + expectFailureMessage(@"expected to not equal <1>, got <1>", ^{ + expect(@1).toNot(equal(@1)); + }); + expectFailureMessage(@"expected to not equal , got ", ^{ + expect("bar").toNot(equal("bar")); + }); + expectFailureMessage(@"expected to equal , got ", ^{ + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 5))); + }); + + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSInteger)1).to(equal((NSInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSUInteger)1).to(equal((NSUInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1).to(equal(2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1.0).to(equal(2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((float)1.0).to(equal((float)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((double)1.0).to(equal((double)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((long long)1.0).to(equal((long long)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((unsigned long long)1.0).to(equal((unsigned long long)2.0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(NULL).to(equal(NULL)); + }); + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(nil).to(equal(nil)); + }); + expectNilFailureMessage(@"expected to not equal , got ", ^{ + expect(nil).toNot(equal(nil)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m @@ -0,0 +1,174 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCHaveCountTest : XCTestCase + +@end + +@implementation ObjCHaveCountTest + +- (void)testHaveCountForNSArray { + expect(@[@1, @2, @3]).to(haveCount(@3)); + expect(@[@1, @2, @3]).notTo(haveCount(@1)); + + expect(@[]).to(haveCount(@0)); + expect(@[@1]).notTo(haveCount(@0)); + + expect(@[@1, @2, @3]).to(haveCount(3)); + expect(@[@1, @2, @3]).notTo(haveCount(1)); + + expect(@[]).to(haveCount(0)); + expect(@[@1]).notTo(haveCount(0)); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSDictionary { + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@1)); + + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSHashtable { + NSHashTable *const table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + [table addObject:@2]; + [table addObject:@3]; + + expect(table).to(haveCount(@3)); + expect(table).notTo(haveCount(@1)); + + expect(table).to(haveCount(3)); + expect(table).notTo(haveCount(1)); + + NSString *msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(@1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(@3)); + }); + + + msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSSet { + NSSet *const set = [NSSet setWithArray:@[@1, @2, @3]]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSIndexSet { + NSIndexSet *const set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForUnsupportedTypes { + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(6)); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m @@ -0,0 +1,33 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCMatchTest : XCTestCase + +@end + +@implementation ObjCMatchTest + +- (void)testPositiveMatches { + expect(@"11:14").to(match(@"\\d{2}:\\d{2}")); + expect(@"hello").toNot(match(@"\\d{2}:\\d{2}")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(@"hello").to(match(@"\\d{2}:\\d{2}")); + }); + expectFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got <11:22>", ^{ + expect(@"11:22").toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).to(match(@"\\d{2}:\\d{2}")); + }); + expectNilFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..9b5a378 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m @@ -0,0 +1,178 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCRaiseExceptionTest : XCTestCase + +@end + +@implementation ObjCRaiseExceptionTest + +- (void)testPositiveMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ @throw exception; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException().named(NSInvalidArgumentException)); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food")); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"})); + + expectAction(^{ }).toNot(raiseException()); +} + +- (void)testPositiveMatchesWithBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); +} + +- (void)testNegativeMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + + expectFailureMessage(@"expected to raise any exception, got no exception", ^{ + expectAction(^{ }).to(raiseException()); + }); + + expectFailureMessage(@"expected to raise exception with name , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(@"foo")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"cakes")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason with userInfo <{k = v;}>, got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"k": @"v"})); + }); + + expectFailureMessage(@"expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }", ^{ + expectAction(^{ [exception raise]; }).toNot(raiseException()); + }); +} + +- (void)testNegativeMatchesWithPassingBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectFailureMessage(@"expected to raise exception that satisfies block, got no exception", ^{ + expect(exception).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"LOL")); + })); + }); + + NSString *outerFailureMessage = @"expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).toNot(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(@"foo"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"bar"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); +} + +- (void)testNegativeMatchesWithNegativeBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + NSString *outerFailureMessage; + + NSString *const innerFailureMessage = @"expected to equal , got "; + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m new file mode 100644 index 0000000..5b38b83 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAllOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAllOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAllOf(equal(@2), beLessThan(@3))); + expect(@2).toNot(satisfyAllOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAllOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).toNot(satisfyAllOf(beTrue(), beFalse())); + expect(@YES).toNot(satisfyAllOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAllOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match all of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, and {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAllOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAllOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAllOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAnyOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAnyOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAnyOf(equal(@2), equal(@3))); + expect(@2).toNot(satisfyAnyOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAnyOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).to(satisfyAnyOf(beTrue(), beFalse())); + expect(@YES).to(satisfyAnyOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAnyOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match one of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, or {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAnyOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAnyOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAnyOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m @@ -0,0 +1,21 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSyncTest : XCTestCase + +@end + +@implementation ObjCSyncTest + +- (void)testFailureExpectation { + expectFailureMessage(@"fail() always fails", ^{ + fail(); + }); + + expectFailureMessage(@"This always fails", ^{ + failWithMessage(@"This always fails"); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m @@ -0,0 +1,52 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCUserDescriptionTest : XCTestCase + +@end + +@implementation ObjCUserDescriptionTest + +- (void)testToWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to equal <2>, got <1>", ^{ + expect(@1).toWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).toNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testNotToWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).notToWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToEventuallyWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to eventually equal <2>, got <1>", ^{ + expect(@1).toEventuallyWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToEventuallyNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toEventuallyNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToNotEventuallyWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toNotEventuallyWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m @@ -0,0 +1,31 @@ +@import XCTest; +@import Nimble; + +@interface ObjcStringersTest : XCTestCase + +@end + +@implementation ObjcStringersTest + +- (void)testItCanStringifyArrays { + NSArray *array = @[@1, @2, @3]; + NSString *result = NMBStringify(array); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItCanStringifyIndexSets { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + NSString *result = NMBStringify(indexSet); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItRoundsLongDecimals { + NSNumber *num = @291.123782163; + NSString *result = NMBStringify(num); + + expect(result).to(equal(@"291.1238")); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/script/release b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/script/release new file mode 100755 index 0000000..f61c0dc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/script/release @@ -0,0 +1,187 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Nimble +PODSPEC=Nimble.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=/tmp/nimble.release.notes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "---------------- Released as $VERSION_TAG ----------------" +echo + +echo +echo "Pushing to pod trunk..." + +# NOTE: remove allow-warnings after v9.0.0 of Nimble +$POD trunk push "$PODSPEC" --allow-warnings + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for GitHub styling." +echo " - Announce!" + +open "https://github.com/Quick/Nimble/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/test b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/test new file mode 100755 index 0000000..0766351 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Externals/Nimble/test @@ -0,0 +1,156 @@ +#!/bin/bash + +GREEN="\033[0;32m" +CLEAR="\033[0m" + +if which xcodebuild > /dev/null; then + echo -e "Gathering ${GREEN}xcodebuild sdk versions${CLEAR}..." + BUILD_DIR=`pwd`/build + LATEST_IOS_SDK_VERSION=`xcodebuild -showsdks | grep iphonesimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_TVOS_SDK_VERSION=`xcodebuild -showsdks | grep appletvsimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_MACOS_SDK_VERSION=`xcodebuild -showsdks | grep 'macosx' | cut -d ' ' -f 3 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + BUILD_IOS_SDK_VERSION=${NIMBLE_BUILD_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + RUNTIME_IOS_SDK_VERSION=${NIMBLE_RUNTIME_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + BUILD_TVOS_SDK_VERSION=${NIMBLE_BUILD_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + RUNTIME_TVOS_SDK_VERSION=${NIMBLE_RUNTIME_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + BUILD_MACOS_SDK_VERSION=${NIMBLE_BUILD_MACOS_SDK_VERSION:-$LATEST_MACOS_SDK_VERSION} +fi + +set -e + +function color_if_overridden { + local actual=$1 + local env_var=$2 + if [ -z "$env_var" ]; then + printf "$actual" + else + printf "$GREEN$actual$CLEAR" + fi +} + +function print_env { + echo "=== Environment ===" + echo " iOS:" + echo " Latest iOS SDK: $LATEST_IOS_SDK_VERSION" + echo " Building with iOS SDK: `color_if_overridden $BUILD_IOS_SDK_VERSION $NIMBLE_BUILD_IOS_SDK_VERSION`" + echo " Running with iOS SDK: `color_if_overridden $RUNTIME_IOS_SDK_VERSION $NIMBLE_RUNTIME_IOS_SDK_VERSION`" + echo + echo " tvOS:" + echo " Latest tvOS SDK: $LATEST_TVOS_SDK_VERSION" + echo " Building with tvOS SDK: `color_if_overridden $BUILD_TVOS_SDK_VERSION $NIMBLE_BUILD_TVOS_SDK_VERSION`" + echo " Running with tvOS SDK: `color_if_overridden $RUNTIME_TVOS_SDK_VERSION $NIMBLE_RUNTIME_TVOS_SDK_VERSION`" + echo + echo " macOS:" + echo " Latest macOS SDK: $LATEST_MACOS_SDK_VERSION" + echo " Building with macOS SDK: `color_if_overridden $BUILD_MACOS_SDK_VERSION $NIMBLE_BUILD_MACOS_SDK_VERSION`" + echo + echo "======= END =======" + echo +} + +function run { + echo -e "$GREEN==>$CLEAR $@" + "$@" +} + +function test_ios { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPad Air,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building + + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPhone 5s,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_tvos { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-tvOS" -configuration "Debug" -sdk "appletvsimulator$BUILD_TVOS_SDK_VERSION" -destination "name=Apple TV 1080p,OS=$RUNTIME_TVOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_macos { + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-macOS" -configuration "Debug" -sdk "macosx$BUILD_MACOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_podspec { + echo "Gathering CocoaPods installation information..." + run bundle exec pod --version + echo "Linting podspec..." + # Note: remove `--allow-warnings` once old Matcher API has been removed + run bundle exec pod lib lint Nimble.podspec --allow-warnings +} + +function test_swiftpm { + if [ -d .build ]; then + run swift build --clean + fi + run swift build && swift test +} + +function test_swiftpm_docker { + run docker build -t nimble-tests -f Dockerfile.test --no-cache . + run docker run -it --privileged=true nimble-tests +} + +function test() { + test_ios + test_tvos + test_macos + + if which swift-test; then + test_swiftpm + else + echo "Not testing with the Swift Package Manager because swift-test is not installed" + fi + + if which docker; then + test_swiftpm_docker + else + echo "Not testing linux in docker container since docker is not in PATH!" + fi +} + +function clean { + run rm -rf ~/Library/Developer/Xcode/DerivedData\; true +} + +function help { + echo "Usage: $0 COMMANDS" + echo + echo "COMMANDS:" + echo " all - Runs the all tests of macos, ios and tvos" + echo " clean - Cleans the derived data directory of Xcode. Assumes default location" + echo " help - Displays this help" + echo " ios - Runs the tests as an iOS device" + echo " macos - Runs the tests on macOS 10.10 (Yosemite and newer only)" + echo " podspec - Runs pod lib lint against the podspec to detect breaking changes" + echo " swiftpm - Runs the tests built by the Swift Package Manager" + echo " swiftpm_docker - Runs the tests built by the Swift Package Manager in a docker linux container" + echo " tvos - Runs the tests as an tvOS device" + echo + exit 1 +} + +function main { + print_env + for arg in $@ + do + case "$arg" in + clean) clean ;; + ios) test_ios ;; + tvos) test_tvos ;; + macos) test_macos ;; + podspec) test_podspec ;; + test) test ;; + all) test ;; + swiftpm) test_swiftpm ;; + swiftpm_docker) test_swiftpm_docker ;; + help) help ;; + esac + done + + if [ $# -eq 0 ]; then + clean + test + fi +} + +main $@ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile new file mode 100644 index 0000000..716d667 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem 'cocoapods', '~> 1.5.0' +gem 'danger' +gem 'danger-swiftlint' diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile.lock b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile.lock new file mode 100644 index 0000000..9a0bf21 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Gemfile.lock @@ -0,0 +1,117 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) + atomos (0.1.2) + claide (1.0.2) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored (1.2) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + cork (0.2.0) + colored (~> 1.2) + danger (4.0.4) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored (~> 1.2) + cork (~> 0.1) + faraday (~> 0.9) + faraday-http-cache (~> 1.0) + git (~> 1) + kramdown (~> 1.5) + octokit (~> 4.2) + terminal-table (~> 1) + danger-swiftlint (0.2.1) + danger + escape (0.0.4) + faraday (0.10.1) + multipart-post (>= 1.2, < 3) + faraday-http-cache (1.3.1) + faraday (~> 0.8) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + git (1.3.0) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + kramdown (1.13.2) + minitest (5.11.3) + molinillo (0.6.5) + multipart-post (2.0.0) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + octokit (4.6.2) + sawyer (~> 0.8.0, >= 0.5.3) + open4 (1.3.4) + public_suffix (2.0.5) + ruby-macho (1.1.0) + sawyer (0.8.1) + addressable (>= 2.3.5, < 2.6) + faraday (~> 0.8, < 1.0) + terminal-table (1.7.3) + unicode-display_width (~> 1.1.1) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + unicode-display_width (1.1.2) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 1.5.0) + danger + danger-swiftlint + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/LICENSE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/LICENSE new file mode 100644 index 0000000..e900165 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014, Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.resolved b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.resolved new file mode 100644 index 0000000..635972c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Nimble", + "repositoryURL": "https://github.com/Quick/Nimble.git", + "state": { + "branch": null, + "revision": "21f4fed2052cea480f5f1d2044d45aa25fdfb988", + "version": "7.1.1" + } + } + ] + }, + "version": 1 +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.swift new file mode 100644 index 0000000..07b93b4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package.swift @@ -0,0 +1,47 @@ +// swift-tools-version:3.1 + +import Foundation +import PackageDescription + +var isTesting: Bool { + guard let value = ProcessInfo.processInfo.environment["SWIFT_PACKAGE_TEST_Quick"] else { return false } + return NSString(string: value).boolValue +} + +var package = Package( + name: "Quick", + targets: { +#if os(macOS) + return [ + Target(name: "QuickSpecBase"), + Target(name: "Quick", dependencies: [ "QuickSpecBase" ]), + Target(name: "QuickTests", dependencies: [ "Quick" ]), + ] +#else + return [ + Target(name: "Quick"), + Target(name: "QuickTests", dependencies: [ "Quick" ]), + ] +#endif + }(), + exclude: { + var excludes = [ + "Sources/QuickObjectiveC", + "Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m", + "Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m", + "Tests/QuickTests/QuickTests/FunctionalTests/ObjC", + "Tests/QuickTests/QuickTests/Helpers", + "Tests/QuickTests/QuickTests/QuickConfigurationTests.m", + ] +#if !os(macOS) + excludes.append("Sources/QuickSpecBase") +#endif + return excludes + }() +) + +if isTesting { + package.dependencies.append(contentsOf: [ + .Package(url: "https://github.com/Quick/Nimble.git", majorVersion: 7), + ]) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package@swift-4.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package@swift-4.swift new file mode 100644 index 0000000..7f230fd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Package@swift-4.swift @@ -0,0 +1,40 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Quick", + products: [ + .library(name: "Quick", targets: ["Quick"]), + ], + dependencies: [ + .package(url: "https://github.com/Quick/Nimble.git", from: "7.0.1"), + ], + targets: { + var targets: [Target] = [ + .testTarget( + name: "QuickTests", + dependencies: [ "Quick", "Nimble" ], + exclude: [ + "QuickAfterSuiteTests/AfterSuiteTests+ObjC.m", + "QuickFocusedTests/FocusedTests+ObjC.m", + "QuickTests/FunctionalTests/ObjC", + "QuickTests/Helpers", + "QuickTests/QuickConfigurationTests.m", + ] + ), + ] +#if os(macOS) + targets.append(contentsOf: [ + .target(name: "QuickSpecBase", dependencies: []), + .target(name: "Quick", dependencies: [ "QuickSpecBase" ]), + ]) +#else + targets.append(contentsOf: [ + .target(name: "Quick", dependencies: []), + ]) +#endif + return targets + }(), + swiftLanguageVersions: [3] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h new file mode 100644 index 0000000..b934bcb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h @@ -0,0 +1,13 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +@import Quick; + +@interface ___FILEBASENAMEASIDENTIFIER___ : QuickConfiguration + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m new file mode 100644 index 0000000..cd3f486 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m @@ -0,0 +1,17 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +#import "___FILEBASENAMEASIDENTIFIER___.h" + +@implementation ___FILEBASENAMEASIDENTIFIER___ + ++ (void)configure:(Configuration *)configuration { + +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..ae0acbb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift @@ -0,0 +1,15 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +import Quick + +class ___FILEBASENAMEASIDENTIFIER___: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000..5cb4ae9 Binary files /dev/null and b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns differ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..146a6df --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist @@ -0,0 +1,73 @@ + + + + + Kind + Xcode.IDEKit.TextSubstitutionFileTemplateKind + Description + A QuickConfiguration subclass. + Summary + A QuickConfiguration subclass, overload +configure: to configure the behaviour when running specs, shared examples that are used across spec files. + SortOrder + 1 + BuildableType + Test + DefaultCompletionName + Spec + Options + + + Description + Name of the Quick Configuration + Identifier + productName + Name + QuickConfiguration Name: + NotPersisted + + Required + + Type + text + + + AllowedTypes + + Swift + + public.swift-source + + Objective-C + + public.objective-c-source + public.objective-c-plus-plus-source + + + Default + Swift + Description + The implementation language + Identifier + languageChoice + MainTemplateFiles + + Objective-C + ___FILEBASENAME___.m + Swift + ___FILEBASENAME___.swift + + Name + Language: + Required + Yes + Type + popup + Values + + Swift + Objective-C + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m new file mode 100644 index 0000000..3e8da5b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m @@ -0,0 +1,14 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +#import +#import + +QuickSpecBegin(___FILEBASENAMEASIDENTIFIER___) + +QuickSpecEnd diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..a8371cf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift @@ -0,0 +1,16 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +import Quick +import Nimble + +class ___FILEBASENAMEASIDENTIFIER___: QuickSpec { + override func spec() { + + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000..5cb4ae9 Binary files /dev/null and b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns differ diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..7b8088f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist @@ -0,0 +1,73 @@ + + + + + Kind + Xcode.IDEKit.TextSubstitutionFileTemplateKind + Description + A class implementing a Quick spec. + Summary + A class implementing a Quick spec + SortOrder + 1 + BuildableType + Test + DefaultCompletionName + Spec + Options + + + Description + Name of the Quick spec class + Identifier + productName + Name + Spec Name: + NotPersisted + + Required + + Type + text + + + AllowedTypes + + Swift + + public.swift-source + + Objective-C + + public.objective-c-source + public.objective-c-plus-plus-source + + + Default + Swift + Description + The implementation language + Identifier + languageChoice + MainTemplateFiles + + Objective-C + ___FILEBASENAME___.m + Swift + ___FILEBASENAME___.swift + + Name + Language: + Required + Yes + Type + popup + Values + + Swift + Objective-C + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.podspec b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.podspec new file mode 100644 index 0000000..f268407 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.podspec @@ -0,0 +1,38 @@ +Pod::Spec.new do |s| + s.name = "Quick" + s.version = "1.3.0" + s.summary = "The Swift (and Objective-C) testing framework." + + s.description = <<-DESC + Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo. + DESC + + s.homepage = "https://github.com/Quick/Quick" + s.license = { :type => "Apache 2.0", :file => "LICENSE" } + + s.author = "Quick Contributors" + s.ios.deployment_target = "7.0" + s.osx.deployment_target = "10.9" + s.tvos.deployment_target = '9.0' + + s.source = { :git => "https://github.com/Quick/Quick.git", :tag => "v#{s.version}" } + s.source_files = "Sources/**/*.{swift,h,m}" + + s.public_header_files = [ + 'Sources/QuickObjectiveC/Configuration/QuickConfiguration.h', + 'Sources/QuickObjectiveC/DSL/QCKDSL.h', + 'Sources/QuickObjectiveC/Quick.h', + 'Sources/QuickObjectiveC/QuickSpec.h', + ] + + s.exclude_files = [ + 'Sources/Quick/Configuration/QuickConfiguration.swift', + 'Sources/Quick/QuickSpec.swift', + 'Sources/Quick/QuickMain.swift', + ] + + s.framework = "XCTest" + s.requires_arc = true + s.user_target_xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(PLATFORM_DIR)/Developer/Library/Frameworks' } + s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO' } +end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b8e2e96 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj @@ -0,0 +1,2713 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 732D8D691E516780008558BD /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 732D8D6A1E516780008558BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + 732D8D6D1E516789008558BD /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1F118CDF1BDCA4AB005013A2 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 1F118CF51BDCA4BB005013A2 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 1F118CFB1BDCA536005013A2 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + 1F118CFC1BDCA536005013A2 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + 1F118CFD1BDCA536005013A2 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + 1F118CFE1BDCA536005013A2 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + 1F118CFF1BDCA536005013A2 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + 1F118D001BDCA536005013A2 /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + 1F118D011BDCA536005013A2 /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + 1F118D021BDCA536005013A2 /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + 1F118D031BDCA536005013A2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 1F118D041BDCA536005013A2 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 1F118D051BDCA536005013A2 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + 1F118D061BDCA536005013A2 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 1F118D071BDCA536005013A2 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 1F118D081BDCA536005013A2 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + 1F118D091BDCA536005013A2 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 1F118D0C1BDCA543005013A2 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + 1F118D0D1BDCA547005013A2 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + 1F118D0E1BDCA547005013A2 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + 1F118D0F1BDCA54B005013A2 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + 1F118D101BDCA556005013A2 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + 1F118D111BDCA556005013A2 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + 1F118D121BDCA556005013A2 /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + 1F118D131BDCA556005013A2 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 1F118D141BDCA556005013A2 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + 1F118D151BDCA556005013A2 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + 1F118D161BDCA556005013A2 /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + 1F118D171BDCA556005013A2 /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 1F118D181BDCA556005013A2 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + 1F118D191BDCA556005013A2 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 1F118D1A1BDCA556005013A2 /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + 1F118D1B1BDCA556005013A2 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 1F118D1C1BDCA556005013A2 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + 1F118D1D1BDCA556005013A2 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 1F118D201BDCA556005013A2 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + 1F118D211BDCA556005013A2 /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 1F118D221BDCA556005013A2 /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + 1F118D231BDCA556005013A2 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 1F118D241BDCA561005013A2 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + 1F118D251BDCA561005013A2 /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + 1F118D261BDCA5AF005013A2 /* World+DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC81B110699006F61EC /* World+DSL.h */; }; + 1F118D271BDCA5AF005013A2 /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC21B1105BC006F61EC /* World.h */; }; + 1F118D291BDCA5B6005013A2 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2A1BDCA5B6005013A2 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2B1BDCA5B6005013A2 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2C1BDCA5B6005013A2 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D351BDCA657005013A2 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D341BDCA657005013A2 /* Nimble.framework */; }; + 1F118D371BDCA65C005013A2 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D361BDCA65C005013A2 /* Nimble.framework */; }; + 1F118D381BDCA6E1005013A2 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + 1F118D391BDCA6E6005013A2 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + 1FD0CFAD1AFA0B8C00874CC1 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 34C586011C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586021C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586031C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586041C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586051C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586061C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586081C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34C586091C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34C5860A1C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 34F375AB19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 34F375AC19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 34F375BB19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 34F375BC19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 470D6ECB1A43442400043E50 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 470D6ECC1A43442900043E50 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 471590401A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 471590411A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 4728253B1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 4728253C1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 4748E8941A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 4748E8951A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 47876F7D1A49AD63002575C7 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 47876F7E1A49AD71002575C7 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 479C31E31A36171B00DA8718 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 479C31E41A36172700DA8718 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 47FAEA361A3F49E6005A1D2F /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 47FAEA371A3F49EB005A1D2F /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + 5A5D11A7194740E000F6D13D /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 64076CEF1D6D7C2000E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + 64076CF01D6D7C2000E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 64076D021D6D7CD600E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + 64076D031D6D7CD600E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 64076D141D6D7CEA00E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 64076D151D6D7CEA00E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D361BDCA65C005013A2 /* Nimble.framework */; }; + 64076D211D6D7E4D00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D221D6D7E5B00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D231D6D7E6B00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D261D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + 64076D271D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + 7B44ADBE1C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B44ADBF1C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B44ADC01C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B5358CE1C3D4FBC00A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 7B5358CF1C3D4FBE00A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 7B5358D01C3D4FC000A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 8D010A571C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + 8D010A581C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + 8D010A591C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + 96327C631C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */ = {isa = PBXBuildFile; fileRef = 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */; }; + 96327C641C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */ = {isa = PBXBuildFile; fileRef = 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */; }; + 96327C651C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */ = {isa = PBXBuildFile; fileRef = 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */; }; + 96327C661C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + 96327C671C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + 96327C681C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + AE4E58131C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58141C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58151C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58161C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58171C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58181C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AED9C8631CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + AED9C8641CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + AED9C8651CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + CD264DBD1DDA147A0038B0EB /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + CE175D4E1E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE175D4F1E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE175D501E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE4A578A1EA5DC270063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE4A578E1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57911EA7252E0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57921EA725300063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57931EA725420063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE4A57941EA725440063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE57CEDD1C430BD200D63004 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE57CEDE1C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE57CEDF1C430BD200D63004 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE57CEE01C430BD200D63004 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE57CEE11C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + CE590E1A1C431FE300253D19 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE590E1B1C431FE300253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE590E1C1C431FE300253D19 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE590E1D1C431FE300253D19 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE590E1E1C431FE300253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + CE590E1F1C431FE400253D19 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE590E201C431FE400253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE590E211C431FE400253D19 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE590E221C431FE400253D19 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE590E231C431FE400253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + DA07722E1A4E5B7B0098839D /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA07722F1A4E5B7C0098839D /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA169E4819FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + DA169E4919FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + DA3E7A341A1E66C600CCE408 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DA3E7A351A1E66CB00CCE408 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DA408BE219FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + DA408BE319FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + DA5663EE1A4C8D8500193C88 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + DA5663F41A4C8D9A00193C88 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + DA5CBB491EAFA61A00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA5CBB4A1EAFA61C00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA5CBB4B1EAFA61D00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA6B30181A4DB0D500FFB148 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + DA6B30191A4DB0D500FFB148 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + DA8940F01B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + DA8940F11B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + DA9876B81A4C70EB0004AA17 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + DA9876C11A4C87200004AA17 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + DAD297651AA8129D001D25CD /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + DAEB6B941943873100289F44 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + DAED1EC41B1105BC006F61EC /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC21B1105BC006F61EC /* World.h */; }; + DAED1EC51B1105BC006F61EC /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC21B1105BC006F61EC /* World.h */; }; + DAED1ECA1B110699006F61EC /* World+DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC81B110699006F61EC /* World+DSL.h */; }; + DAED1ECB1B110699006F61EC /* World+DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED1EC81B110699006F61EC /* World+DSL.h */; }; + DAF28BC31A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + DAF28BC41A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + DED3036B1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3036C1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3036D1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3037D1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; + DED3037E1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; + DED3037F1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 047655511949F4CB00B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 047655531949F4CB00B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04765555194A327000B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 1F118CE01BDCA4AB005013A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 1F118CF61BDCA4BB005013A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 64076CE71D6D7C2000E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = "Quick-OSX"; + }; + 64076CFA1D6D7CD600E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 64076D0C1D6D7CEA00E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + DA5663EF1A4C8D8500193C88 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = "Quick-OSX"; + }; + DA9876B91A4C70EB0004AA17 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F118CD51BDCA4AB005013A2 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118D341BDCA657005013A2 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = "Externals/Nimble/build/Debug-appletvos/Nimble.framework"; sourceTree = ""; }; + 1F118D361BDCA65C005013A2 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = "Externals/Nimble/build/Debug-appletvos/Nimble.framework"; sourceTree = ""; }; + 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = XCTestCaseProvider.swift; path = ../../QuickTestHelpers/XCTestCaseProvider.swift; sourceTree = ""; }; + 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorUtility.swift; sourceTree = ""; }; + 34F3759C19515CA700CE1B99 /* Callsite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Callsite.swift; sourceTree = ""; }; + 34F3759E19515CA700CE1B99 /* Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = ""; }; + 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleGroup.swift; sourceTree = ""; }; + 34F375A419515CA700CE1B99 /* QuickSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickSpec.h; sourceTree = ""; }; + 34F375A519515CA700CE1B99 /* QuickSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickSpec.m; sourceTree = ""; }; + 34F375A619515CA700CE1B99 /* World.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; + 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AfterEachTests+ObjC.m"; sourceTree = ""; }; + 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PendingTests+ObjC.m"; sourceTree = ""; }; + 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SharedExamplesTests+ObjC.m"; sourceTree = ""; }; + 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SharedExamples+BeforeEachTests+ObjC.m"; sourceTree = ""; }; + 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BeforeSuiteTests+ObjC.m"; sourceTree = ""; }; + 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ItTests+ObjC.m"; sourceTree = ""; }; + 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BeforeEachTests+ObjC.m"; sourceTree = ""; }; + 5A5D117C19473F2100F6D13D /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterSuiteTests.swift; sourceTree = ""; }; + 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AfterSuiteTests+ObjC.m"; sourceTree = ""; }; + 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HooksPhase.swift; sourceTree = ""; }; + 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextTests.swift; sourceTree = ""; }; + 8D010A561C11726F00633E2B /* DescribeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DescribeTests.swift; sourceTree = ""; }; + 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "QuickSpec+QuickSpec_MethodList.h"; sourceTree = ""; }; + 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "QuickSpec+QuickSpec_MethodList.m"; sourceTree = ""; }; + AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+QCKSuspendObservation.m"; sourceTree = ""; }; + AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossReferencingSpecs.swift; sourceTree = ""; }; + CD261AC81DEC8B0000A8863C /* QuickConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickConfiguration.swift; sourceTree = ""; }; + CD3451461E4703D4000C8633 /* QuickMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickMain.swift; sourceTree = ""; }; + CD3451471E4703D4000C8633 /* QuickSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickSpec.swift; sourceTree = ""; }; + CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Behavior.swift; sourceTree = ""; }; + CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BehaviorTests.swift; sourceTree = ""; }; + CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests_BehaviorTests_Behaviors.swift; sourceTree = ""; }; + CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+CurrentTestBundle.swift"; sourceTree = ""; }; + CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickSelectedTestSuiteBuilder.swift; sourceTree = ""; }; + CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickTestSuite.swift; sourceTree = ""; }; + CE57CEDB1C430BD200D63004 /* URL+FileName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+FileName.swift"; sourceTree = ""; }; + CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestSuite+QuickTestSuiteBuilder.m"; sourceTree = ""; }; + DA02C91819A8073100093156 /* ExampleMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleMetadata.swift; sourceTree = ""; }; + DA05D60F19F73A3800771050 /* AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterEachTests.swift; sourceTree = ""; }; + DA169E4719FF5DF100619816 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; + DA3124E219FCAEE8002858A7 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + DA3124E319FCAEE8002858A7 /* QCKDSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKDSL.h; sourceTree = ""; }; + DA3124E419FCAEE8002858A7 /* QCKDSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKDSL.m; sourceTree = ""; }; + DA3124E519FCAEE8002858A7 /* World+DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "World+DSL.swift"; sourceTree = ""; }; + DA408BDF19FF5599005DF92A /* Closures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Closures.swift; sourceTree = ""; }; + DA408BE019FF5599005DF92A /* ExampleHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleHooks.swift; sourceTree = ""; }; + DA408BE119FF5599005DF92A /* SuiteHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuiteHooks.swift; sourceTree = ""; }; + DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrentSpecTests.swift; sourceTree = ""; }; + DA6B30171A4DB0D500FFB148 /* Filter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; + DA7AE6F019FC493F000AFDCE /* ItTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItTests.swift; sourceTree = ""; }; + DA87078219F48775008C04AC /* BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeEachTests.swift; sourceTree = ""; }; + DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FailureUsingXCTAssertTests+ObjC.m"; sourceTree = ""; }; + DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfigurationTests.m; sourceTree = ""; }; + DA8F919519F31680006F6675 /* QCKSpecRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKSpecRunner.h; sourceTree = ""; }; + DA8F919619F31680006F6675 /* QCKSpecRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKSpecRunner.m; sourceTree = ""; }; + DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickTestsBridgingHeader.h; sourceTree = ""; }; + DA8F919819F31680006F6675 /* XCTestObservationCenter+QCKSuspendObservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCTestObservationCenter+QCKSuspendObservation.h"; sourceTree = ""; }; + DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FailureTests+ObjC.m"; sourceTree = ""; }; + DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeSuiteTests.swift; sourceTree = ""; }; + DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExamplesTests.swift; sourceTree = ""; }; + DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests_SharedExamplesTests_SharedExamples.swift; sourceTree = ""; }; + DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DA9876BF1A4C87200004AA17 /* FocusedTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FocusedTests.swift; sourceTree = ""; }; + DA9876C01A4C87200004AA17 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAA63EA219F7637300CD0A3B /* PendingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingTests.swift; sourceTree = ""; }; + DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SharedExamples+BeforeEachTests.swift"; sourceTree = ""; }; + DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEachTests.swift"; sourceTree = ""; }; + DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEach.swift"; sourceTree = ""; }; + DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEach.swift"; sourceTree = ""; }; + DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEachTests.swift"; sourceTree = ""; }; + DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickConfiguration.h; sourceTree = ""; }; + DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfiguration.m; sourceTree = ""; }; + DAEB6B8E1943873100289F44 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DAEB6B921943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAEB6B931943873100289F44 /* Quick.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Quick.h; sourceTree = ""; }; + DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DAEB6B9F1943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAED1EC21B1105BC006F61EC /* World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = World.h; sourceTree = ""; }; + DAED1EC81B110699006F61EC /* World+DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "World+DSL.h"; sourceTree = ""; }; + DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FocusedTests+ObjC.m"; sourceTree = ""; }; + DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSString+C99ExtendedIdentifier.swift"; sourceTree = ""; }; + DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleModuleNameTests.swift; sourceTree = ""; }; + F8100E901A1E4447007595ED /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F118CD11BDCA4AB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDB1BDCA4AB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118CDF1BDCA4AB005013A2 /* Quick.framework in Frameworks */, + 1F118D351BDCA657005013A2 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CED1BDCA4BB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118CF51BDCA4BB005013A2 /* Quick.framework in Frameworks */, + 1F118D371BDCA65C005013A2 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117819473F2100F6D13D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118319473F2100F6D13D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */, + DA3E7A351A1E66CB00CCE408 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CEE1D6D7C2000E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076CEF1D6D7C2000E2B499 /* Quick.framework in Frameworks */, + 64076CF01D6D7C2000E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D011D6D7CD600E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D021D6D7CD600E2B499 /* Quick.framework in Frameworks */, + 64076D031D6D7CD600E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D131D6D7CEA00E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D141D6D7CEA00E2B499 /* Quick.framework in Frameworks */, + 64076D151D6D7CEA00E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E51A4C8D8500193C88 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA5663EE1A4C8D8500193C88 /* Quick.framework in Frameworks */, + 1FD0CFAD1AFA0B8C00874CC1 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876AF1A4C70EB0004AA17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA9876B81A4C70EB0004AA17 /* Quick.framework in Frameworks */, + DAD297651AA8129D001D25CD /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8A1943873100289F44 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B961943873100289F44 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA3E7A341A1E66C600CCE408 /* Nimble.framework in Frameworks */, + DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F118D331BDCA645005013A2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1F118D361BDCA65C005013A2 /* Nimble.framework */, + 1F118D341BDCA657005013A2 /* Nimble.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 64076D1C1D6D7D0B00E2B499 /* QuickAfterSuiteTests */ = { + isa = PBXGroup; + children = ( + 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */, + 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */, + ); + name = QuickAfterSuiteTests; + path = Tests/QuickTests/QuickAfterSuiteTests; + sourceTree = ""; + }; + 6C3983EE1D1E930D00637469 /* QuickObjectiveC */ = { + isa = PBXGroup; + children = ( + 6C3983EF1D1E93B700637469 /* Configuration */, + 6C3983F01D1E93CE00637469 /* DSL */, + DAEB6B931943873100289F44 /* Quick.h */, + DAED1EC21B1105BC006F61EC /* World.h */, + 34F375A419515CA700CE1B99 /* QuickSpec.h */, + 34F375A519515CA700CE1B99 /* QuickSpec.m */, + CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */, + ); + name = QuickObjectiveC; + path = Sources/QuickObjectiveC; + sourceTree = ""; + }; + 6C3983EF1D1E93B700637469 /* Configuration */ = { + isa = PBXGroup; + children = ( + DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */, + DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */, + ); + path = Configuration; + sourceTree = ""; + }; + 6C3983F01D1E93CE00637469 /* DSL */ = { + isa = PBXGroup; + children = ( + DAED1EC81B110699006F61EC /* World+DSL.h */, + DA3124E319FCAEE8002858A7 /* QCKDSL.h */, + DA3124E419FCAEE8002858A7 /* QCKDSL.m */, + ); + path = DSL; + sourceTree = ""; + }; + CDB2AA5E1D6C84CF005600C3 /* ObjC */ = { + isa = PBXGroup; + children = ( + 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */, + 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */, + 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */, + DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */, + DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */, + 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */, + 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */, + 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */, + 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */, + ); + path = ObjC; + sourceTree = ""; + }; + DA169E4619FF5DF100619816 /* Configuration */ = { + isa = PBXGroup; + children = ( + DA169E4719FF5DF100619816 /* Configuration.swift */, + CD261AC81DEC8B0000A8863C /* QuickConfiguration.swift */, + ); + path = Configuration; + sourceTree = ""; + }; + DA3124E119FCAEE8002858A7 /* DSL */ = { + isa = PBXGroup; + children = ( + DA3124E519FCAEE8002858A7 /* World+DSL.swift */, + DA3124E219FCAEE8002858A7 /* DSL.swift */, + ); + path = DSL; + sourceTree = ""; + }; + DA408BDE19FF5599005DF92A /* Hooks */ = { + isa = PBXGroup; + children = ( + DA408BDF19FF5599005DF92A /* Closures.swift */, + DA408BE019FF5599005DF92A /* ExampleHooks.swift */, + DA408BE119FF5599005DF92A /* SuiteHooks.swift */, + 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */, + ); + path = Hooks; + sourceTree = ""; + }; + DA8F919419F31680006F6675 /* Helpers */ = { + isa = PBXGroup; + children = ( + DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */, + DA8F919519F31680006F6675 /* QCKSpecRunner.h */, + DA8F919619F31680006F6675 /* QCKSpecRunner.m */, + 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */, + DA8F919819F31680006F6675 /* XCTestObservationCenter+QCKSuspendObservation.h */, + 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */, + 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */, + AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */, + ); + path = Helpers; + sourceTree = ""; + }; + DA8F919B19F3189D006F6675 /* FunctionalTests */ = { + isa = PBXGroup; + children = ( + DAE714E919FF65A6005905B8 /* Configuration */, + CDB2AA5E1D6C84CF005600C3 /* ObjC */, + DA7AE6F019FC493F000AFDCE /* ItTests.swift */, + 8D010A561C11726F00633E2B /* DescribeTests.swift */, + DA87078219F48775008C04AC /* BeforeEachTests.swift */, + DA05D60F19F73A3800771050 /* AfterEachTests.swift */, + DAA63EA219F7637300CD0A3B /* PendingTests.swift */, + DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */, + DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */, + DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */, + 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */, + AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */, + DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */, + CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */, + DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */, + ); + path = FunctionalTests; + sourceTree = ""; + }; + DA9876BE1A4C87200004AA17 /* QuickFocusedTests */ = { + isa = PBXGroup; + children = ( + DA9876BF1A4C87200004AA17 /* FocusedTests.swift */, + DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */, + DA9876C31A4C87310004AA17 /* Supporting Files */, + ); + name = QuickFocusedTests; + path = Tests/QuickTests/QuickFocusedTests; + sourceTree = ""; + }; + DA9876C31A4C87310004AA17 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DA9876C01A4C87200004AA17 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAE714E919FF65A6005905B8 /* Configuration */ = { + isa = PBXGroup; + children = ( + DAE714F519FF67FF005905B8 /* AfterEach */, + DAE714EA19FF65A6005905B8 /* BeforeEach */, + ); + path = Configuration; + sourceTree = ""; + }; + DAE714EA19FF65A6005905B8 /* BeforeEach */ = { + isa = PBXGroup; + children = ( + DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */, + DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */, + ); + path = BeforeEach; + sourceTree = ""; + }; + DAE714F519FF67FF005905B8 /* AfterEach */ = { + isa = PBXGroup; + children = ( + DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */, + DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */, + ); + path = AfterEach; + sourceTree = ""; + }; + DAEB6B841943873100289F44 = { + isa = PBXGroup; + children = ( + DAEB6B901943873100289F44 /* Quick */, + 6C3983EE1D1E930D00637469 /* QuickObjectiveC */, + DAEB6B9D1943873100289F44 /* QuickTests */, + DA9876BE1A4C87200004AA17 /* QuickFocusedTests */, + 64076D1C1D6D7D0B00E2B499 /* QuickAfterSuiteTests */, + DAEB6B8F1943873100289F44 /* Products */, + 1F118D331BDCA645005013A2 /* Frameworks */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + }; + DAEB6B8F1943873100289F44 /* Products */ = { + isa = PBXGroup; + children = ( + DAEB6B8E1943873100289F44 /* Quick.framework */, + DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */, + 5A5D117C19473F2100F6D13D /* Quick.framework */, + 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */, + DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */, + DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */, + 1F118CD51BDCA4AB005013A2 /* Quick.framework */, + 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */, + 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */, + 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */, + 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */, + 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + DAEB6B901943873100289F44 /* Quick */ = { + isa = PBXGroup; + children = ( + DA169E4619FF5DF100619816 /* Configuration */, + DA3124E119FCAEE8002858A7 /* DSL */, + DA408BDE19FF5599005DF92A /* Hooks */, + CD3451461E4703D4000C8633 /* QuickMain.swift */, + CD3451471E4703D4000C8633 /* QuickSpec.swift */, + 34F375A619515CA700CE1B99 /* World.swift */, + 34F3759E19515CA700CE1B99 /* Example.swift */, + DA02C91819A8073100093156 /* ExampleMetadata.swift */, + 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */, + 34F3759C19515CA700CE1B99 /* Callsite.swift */, + DA6B30171A4DB0D500FFB148 /* Filter.swift */, + CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */, + CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */, + CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */, + DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */, + CE57CEDB1C430BD200D63004 /* URL+FileName.swift */, + 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */, + DAEB6B911943873100289F44 /* Supporting Files */, + CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */, + ); + name = Quick; + path = Sources/Quick; + sourceTree = ""; + }; + DAEB6B911943873100289F44 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DAEB6B921943873100289F44 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAEB6B9D1943873100289F44 /* QuickTests */ = { + isa = PBXGroup; + children = ( + DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */, + DA8F919419F31680006F6675 /* Helpers */, + DAEB6BCD194387D700289F44 /* Fixtures */, + DA8F919B19F3189D006F6675 /* FunctionalTests */, + F8100E941A1E4469007595ED /* Frameworks */, + DAEB6B9E1943873100289F44 /* Supporting Files */, + ); + name = QuickTests; + path = Tests/QuickTests/QuickTests; + sourceTree = ""; + }; + DAEB6B9E1943873100289F44 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DAEB6B9F1943873100289F44 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAEB6BCD194387D700289F44 /* Fixtures */ = { + isa = PBXGroup; + children = ( + DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */, + CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */, + ); + path = Fixtures; + sourceTree = ""; + }; + F8100E941A1E4469007595ED /* Frameworks */ = { + isa = PBXGroup; + children = ( + F8100E901A1E4447007595ED /* Nimble.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F118CD21BDCA4AB005013A2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D2B1BDCA5B6005013A2 /* Quick.h in Headers */, + 1F118D261BDCA5AF005013A2 /* World+DSL.h in Headers */, + 96327C651C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */, + 1F118D271BDCA5AF005013A2 /* World.h in Headers */, + 1F118D2A1BDCA5B6005013A2 /* QCKDSL.h in Headers */, + 1F118D2C1BDCA5B6005013A2 /* QuickSpec.h in Headers */, + 1F118D291BDCA5B6005013A2 /* QuickConfiguration.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117919473F2100F6D13D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */, + 96327C641C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */, + DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */, + DAED1ECB1B110699006F61EC /* World+DSL.h in Headers */, + DAED1EC51B1105BC006F61EC /* World.h in Headers */, + 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */, + 5A5D11A7194740E000F6D13D /* Quick.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8B1943873100289F44 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */, + 96327C631C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h in Headers */, + DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */, + DAED1ECA1B110699006F61EC /* World+DSL.h in Headers */, + DAED1EC41B1105BC006F61EC /* World.h in Headers */, + 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */, + DAEB6B941943873100289F44 /* Quick.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CE61BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick-tvOS" */; + buildPhases = ( + 1F118CD01BDCA4AB005013A2 /* Sources */, + 1F118CD11BDCA4AB005013A2 /* Frameworks */, + 1F118CD21BDCA4AB005013A2 /* Headers */, + 1F118CD31BDCA4AB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-tvOS"; + productName = "Quick-tvOS"; + productReference = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F118CDD1BDCA4AB005013A2 /* Quick - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CE91BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick - tvOSTests" */; + buildPhases = ( + 1F118CDA1BDCA4AB005013A2 /* Sources */, + 1F118CDB1BDCA4AB005013A2 /* Frameworks */, + 1F118CDC1BDCA4AB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F118CE11BDCA4AB005013A2 /* PBXTargetDependency */, + ); + name = "Quick - tvOSTests"; + productName = "Quick-tvOSTests"; + productReference = 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F118CEF1BDCA4BB005013A2 /* QuickFocused - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CF81BDCA4BC005013A2 /* Build configuration list for PBXNativeTarget "QuickFocused - tvOSTests" */; + buildPhases = ( + 1F118CEC1BDCA4BB005013A2 /* Sources */, + 1F118CED1BDCA4BB005013A2 /* Frameworks */, + 1F118CEE1BDCA4BB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F118CF71BDCA4BB005013A2 /* PBXTargetDependency */, + ); + name = "QuickFocused - tvOSTests"; + productName = "QuickFocused-tvOSTests"; + productReference = 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 5A5D117B19473F2100F6D13D /* Quick-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */; + buildPhases = ( + 5A5D117719473F2100F6D13D /* Sources */, + 5A5D117819473F2100F6D13D /* Frameworks */, + 5A5D117919473F2100F6D13D /* Headers */, + 5A5D117A19473F2100F6D13D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-iOS"; + productName = "Quick-iOS"; + productReference = 5A5D117C19473F2100F6D13D /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + 5A5D118519473F2100F6D13D /* Quick - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick - iOSTests" */; + buildPhases = ( + 5A5D118219473F2100F6D13D /* Sources */, + 5A5D118319473F2100F6D13D /* Frameworks */, + 5A5D118419473F2100F6D13D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5A5D118919473F2100F6D13D /* PBXTargetDependency */, + 5A5D11F0194741B500F6D13D /* PBXTargetDependency */, + 5A5D11F2194741B500F6D13D /* PBXTargetDependency */, + 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */, + 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */, + 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */, + 04DC97F7194B831200CE00B6 /* PBXTargetDependency */, + 04DC97FB194B834100CE00B6 /* PBXTargetDependency */, + 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */, + 04DC9803194B836300CE00B6 /* PBXTargetDependency */, + 04DC9807194B838700CE00B6 /* PBXTargetDependency */, + ); + name = "Quick - iOSTests"; + productName = "Quick-iOSTests"; + productReference = 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076CE51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076CF21D6D7C2000E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - macOSTests" */; + buildPhases = ( + 64076CE81D6D7C2000E2B499 /* Sources */, + 64076CEE1D6D7C2000E2B499 /* Frameworks */, + 64076CF11D6D7C2000E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076CE61D6D7C2000E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - macOSTests"; + productName = "QuickFocused-macOSTests"; + productReference = 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076CF81D6D7CD600E2B499 /* QuickAfterSuite - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076D051D6D7CD600E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - iOSTests" */; + buildPhases = ( + 64076CFB1D6D7CD600E2B499 /* Sources */, + 64076D011D6D7CD600E2B499 /* Frameworks */, + 64076D041D6D7CD600E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076CF91D6D7CD600E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - iOSTests"; + productName = "QuickFocused-iOSTests"; + productReference = 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076D0A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076D171D6D7CEA00E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - tvOSTests" */; + buildPhases = ( + 64076D0D1D6D7CEA00E2B499 /* Sources */, + 64076D131D6D7CEA00E2B499 /* Frameworks */, + 64076D161D6D7CEA00E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076D0B1D6D7CEA00E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - tvOSTests"; + productName = "QuickFocused-tvOSTests"; + productReference = 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DA5663E71A4C8D8500193C88 /* QuickFocused - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA5663F31A4C8D8500193C88 /* Build configuration list for PBXNativeTarget "QuickFocused - macOSTests" */; + buildPhases = ( + DA5663E41A4C8D8500193C88 /* Sources */, + DA5663E51A4C8D8500193C88 /* Frameworks */, + DA5663E61A4C8D8500193C88 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DA5663F01A4C8D8500193C88 /* PBXTargetDependency */, + ); + name = "QuickFocused - macOSTests"; + productName = "QuickFocused-macOSTests"; + productReference = DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DA9876B11A4C70EB0004AA17 /* QuickFocused - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA9876BD1A4C70EB0004AA17 /* Build configuration list for PBXNativeTarget "QuickFocused - iOSTests" */; + buildPhases = ( + DA9876AE1A4C70EB0004AA17 /* Sources */, + DA9876AF1A4C70EB0004AA17 /* Frameworks */, + DA9876B01A4C70EB0004AA17 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DA9876BA1A4C70EB0004AA17 /* PBXTargetDependency */, + ); + name = "QuickFocused - iOSTests"; + productName = "QuickFocused-iOSTests"; + productReference = DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DAEB6B8D1943873100289F44 /* Quick-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-macOS" */; + buildPhases = ( + DAEB6B891943873100289F44 /* Sources */, + DAEB6B8A1943873100289F44 /* Frameworks */, + DAEB6B8B1943873100289F44 /* Headers */, + DAEB6B8C1943873100289F44 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-macOS"; + productName = Quick; + productReference = DAEB6B8E1943873100289F44 /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + DAEB6B981943873100289F44 /* Quick - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick - macOSTests" */; + buildPhases = ( + DAEB6B951943873100289F44 /* Sources */, + DAEB6B961943873100289F44 /* Frameworks */, + DAEB6B971943873100289F44 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DAEB6B9C1943873100289F44 /* PBXTargetDependency */, + 047655521949F4CB00B288BB /* PBXTargetDependency */, + 047655541949F4CB00B288BB /* PBXTargetDependency */, + 04765556194A327000B288BB /* PBXTargetDependency */, + 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */, + 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */, + 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */, + 04DC97F9194B834000CE00B6 /* PBXTargetDependency */, + 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */, + 04DC9801194B836100CE00B6 /* PBXTargetDependency */, + 04DC9805194B838400CE00B6 /* PBXTargetDependency */, + 04DC9809194B838B00CE00B6 /* PBXTargetDependency */, + 93625F391951DDC8006B1FE1 /* PBXTargetDependency */, + ); + name = "Quick - macOSTests"; + productName = QuickTests; + productReference = DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DAEB6B851943873100289F44 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0810; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Brian Ivan Gesiak"; + TargetAttributes = { + 1F118CD41BDCA4AB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F118CDD1BDCA4AB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F118CEF1BDCA4BB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 5A5D117B19473F2100F6D13D = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 5A5D118519473F2100F6D13D = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = 5A5D117B19473F2100F6D13D; + }; + 732D8D691E516780008558BD = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + DA5663E71A4C8D8500193C88 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + DA9876B11A4C70EB0004AA17 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + DAEB6B8D1943873100289F44 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + DAEB6B981943873100289F44 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = DAEB6B8D1943873100289F44; + }; + }; + }; + buildConfigurationList = DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DAEB6B841943873100289F44; + productRefGroup = DAEB6B8F1943873100289F44 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DAEB6B8D1943873100289F44 /* Quick-macOS */, + DAEB6B981943873100289F44 /* Quick - macOSTests */, + DA5663E71A4C8D8500193C88 /* QuickFocused - macOSTests */, + 64076CE51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests */, + 5A5D117B19473F2100F6D13D /* Quick-iOS */, + 5A5D118519473F2100F6D13D /* Quick - iOSTests */, + DA9876B11A4C70EB0004AA17 /* QuickFocused - iOSTests */, + 64076CF81D6D7CD600E2B499 /* QuickAfterSuite - iOSTests */, + 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */, + 1F118CDD1BDCA4AB005013A2 /* Quick - tvOSTests */, + 1F118CEF1BDCA4BB005013A2 /* QuickFocused - tvOSTests */, + 64076D0A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests */, + 732D8D691E516780008558BD /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F118CD31BDCA4AB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDC1BDCA4AB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CEE1BDCA4BB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117A19473F2100F6D13D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118419473F2100F6D13D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CF11D6D7C2000E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D041D6D7CD600E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D161D6D7CEA00E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E61A4C8D8500193C88 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876B01A4C70EB0004AA17 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8C1943873100289F44 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B971943873100289F44 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 732D8D6D1E516789008558BD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F118CD01BDCA4AB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96327C681C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */, + 1F118D031BDCA536005013A2 /* World.swift in Sources */, + CE590E201C431FE400253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + 1F118CFC1BDCA536005013A2 /* Configuration.swift in Sources */, + 1F118D021BDCA536005013A2 /* SuiteHooks.swift in Sources */, + 1F118CFB1BDCA536005013A2 /* QuickConfiguration.m in Sources */, + 34C5860A1C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + 1F118D041BDCA536005013A2 /* Example.swift in Sources */, + 1F118CFF1BDCA536005013A2 /* QCKDSL.m in Sources */, + DED3036D1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + CE590E211C431FE400253D19 /* NSBundle+CurrentTestBundle.swift in Sources */, + 1F118D071BDCA536005013A2 /* Callsite.swift in Sources */, + CE590E231C431FE400253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + 1F118D081BDCA536005013A2 /* Filter.swift in Sources */, + 1F118CFD1BDCA536005013A2 /* World+DSL.swift in Sources */, + CE590E221C431FE400253D19 /* URL+FileName.swift in Sources */, + 1F118CFE1BDCA536005013A2 /* DSL.swift in Sources */, + 7B44ADC01C5444940007AF2E /* HooksPhase.swift in Sources */, + 1F118D001BDCA536005013A2 /* Closures.swift in Sources */, + 1F118D051BDCA536005013A2 /* ExampleMetadata.swift in Sources */, + 1F118D061BDCA536005013A2 /* ExampleGroup.swift in Sources */, + CE175D501E8D6B4900EB5E84 /* Behavior.swift in Sources */, + CE590E1F1C431FE400253D19 /* QuickTestSuite.swift in Sources */, + 1F118D091BDCA536005013A2 /* QuickSpec.m in Sources */, + 1F118D011BDCA536005013A2 /* ExampleHooks.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDA1BDCA4AB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D381BDCA6E1005013A2 /* Configuration+BeforeEachTests.swift in Sources */, + 1F118D121BDCA556005013A2 /* ItTests.swift in Sources */, + 1F118D1C1BDCA556005013A2 /* BeforeSuiteTests.swift in Sources */, + 1F118D1D1BDCA556005013A2 /* BeforeSuiteTests+ObjC.m in Sources */, + 1F118D0E1BDCA547005013A2 /* QCKSpecRunner.m in Sources */, + CE4A57931EA725420063C0D4 /* BehaviorTests.swift in Sources */, + 1F118D141BDCA556005013A2 /* FailureTests+ObjC.m in Sources */, + CE4A57911EA7252E0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DED3037F1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + 1F118D0F1BDCA54B005013A2 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + 1F118D101BDCA556005013A2 /* Configuration+AfterEach.swift in Sources */, + 1F118D1A1BDCA556005013A2 /* PendingTests.swift in Sources */, + 1F118D171BDCA556005013A2 /* BeforeEachTests+ObjC.m in Sources */, + 1F118D231BDCA556005013A2 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + 1F118D151BDCA556005013A2 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 1F118D131BDCA556005013A2 /* ItTests+ObjC.m in Sources */, + 1F118D191BDCA556005013A2 /* AfterEachTests+ObjC.m in Sources */, + 1F118D221BDCA556005013A2 /* SharedExamples+BeforeEachTests.swift in Sources */, + AE4E58171C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8651CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 1F118D211BDCA556005013A2 /* SharedExamplesTests+ObjC.m in Sources */, + 1F118D201BDCA556005013A2 /* SharedExamplesTests.swift in Sources */, + 1F118D0C1BDCA543005013A2 /* QuickConfigurationTests.m in Sources */, + 1F118D391BDCA6E6005013A2 /* Configuration+BeforeEach.swift in Sources */, + 1F118D181BDCA556005013A2 /* AfterEachTests.swift in Sources */, + 1F118D1B1BDCA556005013A2 /* PendingTests+ObjC.m in Sources */, + 34C586051C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A591C11726F00633E2B /* DescribeTests.swift in Sources */, + 1F118D111BDCA556005013A2 /* Configuration+AfterEachTests.swift in Sources */, + 1F118D161BDCA556005013A2 /* BeforeEachTests.swift in Sources */, + DA5CBB4B1EAFA61D00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358D01C3D4FC000A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CEC1BDCA4BB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D0D1BDCA547005013A2 /* QCKSpecRunner.m in Sources */, + 34C586061C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */, + 1F118D241BDCA561005013A2 /* FocusedTests.swift in Sources */, + 1F118D251BDCA561005013A2 /* FocusedTests+ObjC.m in Sources */, + AE4E58181C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117719473F2100F6D13D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96327C671C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */, + CE590E1B1C431FE300253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */, + DA408BE319FF5599005DF92A /* Closures.swift in Sources */, + DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */, + 34C586091C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */, + 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */, + DED3036C1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + CE590E1C1C431FE300253D19 /* NSBundle+CurrentTestBundle.swift in Sources */, + DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */, + CE590E1E1C431FE300253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */, + 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */, + CE590E1D1C431FE300253D19 /* URL+FileName.swift in Sources */, + 34F375BC19515CA700CE1B99 /* World.swift in Sources */, + DA169E4919FF5DF100619816 /* Configuration.swift in Sources */, + 7B44ADBF1C5444940007AF2E /* HooksPhase.swift in Sources */, + DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */, + DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */, + 34F375AC19515CA700CE1B99 /* Example.swift in Sources */, + CE175D4F1E8D6B4900EB5E84 /* Behavior.swift in Sources */, + CE590E1A1C431FE300253D19 /* QuickTestSuite.swift in Sources */, + DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */, + DA6B30191A4DB0D500FFB148 /* Filter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118219473F2100F6D13D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, + DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */, + DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */, + DA8940F11B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 4728253C1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */, + DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, + DED3037E1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */, + DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, + DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, + DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, + CE4A578A1EA5DC270063C0D4 /* BehaviorTests.swift in Sources */, + DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */, + DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, + DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */, + 4748E8951A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + CE4A578E1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, + AE4E58151C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8641CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 471590411A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */, + DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */, + DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, + 479C31E41A36172700DA8718 /* ItTests+ObjC.m in Sources */, + 34C586031C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A581C11726F00633E2B /* DescribeTests.swift in Sources */, + 47FAEA371A3F49EB005A1D2F /* BeforeEachTests+ObjC.m in Sources */, + 470D6ECC1A43442900043E50 /* AfterEachTests+ObjC.m in Sources */, + 47876F7E1A49AD71002575C7 /* BeforeSuiteTests+ObjC.m in Sources */, + DA5CBB4A1EAFA61C00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358CF1C3D4FBE00A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CE81D6D7C2000E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D211D6D7E4D00E2B499 /* AfterSuiteTests.swift in Sources */, + CD264DBD1DDA147A0038B0EB /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CFB1D6D7CD600E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D221D6D7E5B00E2B499 /* AfterSuiteTests.swift in Sources */, + 64076D261D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D0D1D6D7CEA00E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D231D6D7E6B00E2B499 /* AfterSuiteTests.swift in Sources */, + 64076D271D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E41A4C8D8500193C88 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA07722E1A4E5B7B0098839D /* QCKSpecRunner.m in Sources */, + 34C586021C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */, + DA5663F41A4C8D9A00193C88 /* FocusedTests.swift in Sources */, + DAF28BC31A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */, + AE4E58141C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876AE1A4C70EB0004AA17 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA07722F1A4E5B7C0098839D /* QCKSpecRunner.m in Sources */, + 34C586041C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */, + DA9876C11A4C87200004AA17 /* FocusedTests.swift in Sources */, + DAF28BC41A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */, + AE4E58161C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B891943873100289F44 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96327C661C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m in Sources */, + CE57CEDE1C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */, + DA408BE219FF5599005DF92A /* Closures.swift in Sources */, + CE57CEDD1C430BD200D63004 /* NSBundle+CurrentTestBundle.swift in Sources */, + DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */, + CE57CEDF1C430BD200D63004 /* QuickTestSuite.swift in Sources */, + 34C586081C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + DED3036B1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */, + 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */, + CE57CEE11C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */, + 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */, + CE57CEE01C430BD200D63004 /* URL+FileName.swift in Sources */, + 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */, + 34F375BB19515CA700CE1B99 /* World.swift in Sources */, + DA169E4819FF5DF100619816 /* Configuration.swift in Sources */, + 7B44ADBE1C5444940007AF2E /* HooksPhase.swift in Sources */, + DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */, + DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */, + CE175D4E1E8D6B4900EB5E84 /* Behavior.swift in Sources */, + 34F375AB19515CA700CE1B99 /* Example.swift in Sources */, + DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */, + DA6B30181A4DB0D500FFB148 /* Filter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B951943873100289F44 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, + DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */, + DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */, + DA8940F01B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 4728253B1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */, + CE4A57941EA725440063C0D4 /* BehaviorTests.swift in Sources */, + DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, + CE4A57921EA725300063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DED3037D1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */, + DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, + DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, + DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, + DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */, + DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, + DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */, + 4748E8941A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, + AE4E58131C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8631CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 471590401A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */, + DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */, + DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, + 479C31E31A36171B00DA8718 /* ItTests+ObjC.m in Sources */, + 34C586011C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A571C11726F00633E2B /* DescribeTests.swift in Sources */, + 47FAEA361A3F49E6005A1D2F /* BeforeEachTests+ObjC.m in Sources */, + 470D6ECB1A43442400043E50 /* AfterEachTests+ObjC.m in Sources */, + 47876F7D1A49AD63002575C7 /* BeforeSuiteTests+ObjC.m in Sources */, + DA5CBB491EAFA61A00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358CE1C3D4FBC00A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 047655521949F4CB00B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 047655511949F4CB00B288BB /* PBXContainerItemProxy */; + }; + 047655541949F4CB00B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 047655531949F4CB00B288BB /* PBXContainerItemProxy */; + }; + 04765556194A327000B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04765555194A327000B288BB /* PBXContainerItemProxy */; + }; + 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F7194B831200CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F9194B834000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FB194B834100CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9801194B836100CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9803194B836300CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9805194B838400CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9807194B838700CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9809194B838B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */; + }; + 1F118CE11BDCA4AB005013A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 1F118CE01BDCA4AB005013A2 /* PBXContainerItemProxy */; + }; + 1F118CF71BDCA4BB005013A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 1F118CF61BDCA4BB005013A2 /* PBXContainerItemProxy */; + }; + 5A5D118919473F2100F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */; + }; + 5A5D11F0194741B500F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */; + }; + 5A5D11F2194741B500F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */; + }; + 64076CE61D6D7C2000E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 64076CE71D6D7C2000E2B499 /* PBXContainerItemProxy */; + }; + 64076CF91D6D7CD600E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 64076CFA1D6D7CD600E2B499 /* PBXContainerItemProxy */; + }; + 64076D0B1D6D7CEA00E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 64076D0C1D6D7CEA00E2B499 /* PBXContainerItemProxy */; + }; + 93625F391951DDC8006B1FE1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */; + }; + DA5663F01A4C8D8500193C88 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = DA5663EF1A4C8D8500193C88 /* PBXContainerItemProxy */; + }; + DA9876BA1A4C70EB0004AA17 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = DA9876B91A4C70EB0004AA17 /* PBXContainerItemProxy */; + }; + DAEB6B9C1943873100289F44 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F118CE71BDCA4AB005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Quick; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CE81BDCA4AB005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + 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", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Quick; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1F118CEA1BDCA4AB005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CEB1BDCA4AB005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1F118CF91BDCA4BC005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CFA1BDCA4BC005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5A5D118F19473F2100F6D13D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + 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", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 5A5D119019473F2100F6D13D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + 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", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5A5D119119473F2100F6D13D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 5A5D119219473F2100F6D13D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 64076CF31D6D7C2000E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 64076CF41D6D7C2000E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 64076D061D6D7CD600E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 64076D071D6D7CD600E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 64076D181D6D7CEA00E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 64076D191D6D7CEA00E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 732D8D6B1E516780008558BD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 732D8D6C1E516780008558BD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DA5663F11A4C8D8500193C88 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DA5663F21A4C8D8500193C88 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + DA9876BB1A4C70EB0004AA17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DA9876BC1A4C70EB0004AA17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DAEB6BA21943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DAEB6BA31943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DAEB6BA51943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + 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", + "$(inherited)", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + DAEB6BA61943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + 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", + "$(inherited)", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + DAEB6BA81943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DAEB6BA91943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F118CE61BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CE71BDCA4AB005013A2 /* Debug */, + 1F118CE81BDCA4AB005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F118CE91BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CEA1BDCA4AB005013A2 /* Debug */, + 1F118CEB1BDCA4AB005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F118CF81BDCA4BC005013A2 /* Build configuration list for PBXNativeTarget "QuickFocused - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CF91BDCA4BC005013A2 /* Debug */, + 1F118CFA1BDCA4BC005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5A5D118F19473F2100F6D13D /* Debug */, + 5A5D119019473F2100F6D13D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5A5D119119473F2100F6D13D /* Debug */, + 5A5D119219473F2100F6D13D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076CF21D6D7C2000E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076CF31D6D7C2000E2B499 /* Debug */, + 64076CF41D6D7C2000E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076D051D6D7CD600E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076D061D6D7CD600E2B499 /* Debug */, + 64076D071D6D7CD600E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076D171D6D7CEA00E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076D181D6D7CEA00E2B499 /* Debug */, + 64076D191D6D7CEA00E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 732D8D6A1E516780008558BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 732D8D6B1E516780008558BD /* Debug */, + 732D8D6C1E516780008558BD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DA5663F31A4C8D8500193C88 /* Build configuration list for PBXNativeTarget "QuickFocused - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA5663F11A4C8D8500193C88 /* Debug */, + DA5663F21A4C8D8500193C88 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DA9876BD1A4C70EB0004AA17 /* Build configuration list for PBXNativeTarget "QuickFocused - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA9876BB1A4C70EB0004AA17 /* Debug */, + DA9876BC1A4C70EB0004AA17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA21943873200289F44 /* Debug */, + DAEB6BA31943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA51943873200289F44 /* Debug */, + DAEB6BA61943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA81943873200289F44 /* Debug */, + DAEB6BA91943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DAEB6B851943873100289F44 /* Project object */; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a459aa8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme new file mode 100644 index 0000000..584e319 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme new file mode 100644 index 0000000..ce4dfe3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme new file mode 100644 index 0000000..fcd9b81 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..48af53a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/README.md new file mode 100644 index 0000000..e6dc0ad --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/README.md @@ -0,0 +1,88 @@ +![](http://f.cl.ly/items/0r1E192C1R0b2g2Q3h2w/QuickLogo_Color.png) + +[![Build Status](https://travis-ci.org/Quick/Quick.svg?branch=master)](https://travis-ci.org/Quick/Quick) +[![CocoaPods](https://img.shields.io/cocoapods/v/Quick.svg)](https://cocoapods.org/pods/Quick) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Platforms](https://img.shields.io/cocoapods/p/Quick.svg)](https://cocoapods.org/pods/Quick) + +Quick is a behavior-driven development framework for Swift and Objective-C. +Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo). + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/QuickSpec%20screenshot.png) + +```swift +// Swift + +import Quick +import Nimble + +class TableOfContentsSpec: QuickSpec { + override func spec() { + describe("the 'Documentation' directory") { + it("has everything you need to get started") { + let sections = Directory("Documentation").sections + expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups")) + expect(sections).to(contain("Installing Quick")) + } + + context("if it doesn't have what you're looking for") { + it("needs to be updated") { + let you = You(awesome: true) + expect{you.submittedAnIssue}.toEventually(beTruthy()) + } + } + } + } +} +``` +#### Nimble +Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md). + +## Swift Version + +Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project. + +|Swift version |Quick version |Nimble version | +|:--------------------|:---------------|:--------------| +|Swift 3 |v1.0.0 or later |v5.0.0 or later| +|Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 | + +## Documentation + +All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile: + +```rb +# Podfile + +use_frameworks! + +target "MyApp" do + # Normal libraries + + abstract_target 'Tests' do + inherit! :search_paths + target "MyAppTests" + target "MyAppUITests" + + pod 'Quick' + pod 'Nimble' + end +end +``` + +## Projects using Quick + +Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them. + +Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick). + +## Who uses Quick + +Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses? + +Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick). + + +## License + +Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details. diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Rakefile b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Rakefile new file mode 100644 index 0000000..a5214a4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Rakefile @@ -0,0 +1,67 @@ +def run(env = {}, command) + system(env, command) or raise "RAKE TASK FAILED: #{command}" +end + +def has_xcodebuild + system "which xcodebuild >/dev/null" +end + +def xcode_action + ENV["XCODE_ACTION"] || "build test" +end + +namespace "podspec" do + desc "Run lint for podspec" + task :lint do + run "bundle exec pod lib lint" + end +end + +namespace "test" do + desc "Run unit tests for all iOS targets" + task :ios do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-iOS -destination 'platform=iOS Simulator,name=iPhone 6' clean #{xcode_action}" + end + + desc "Run unit tests for all tvOS targets" + task :tvos do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 1080p' clean #{xcode_action}" + end + + desc "Run unit tests for all macOS targets" + task :macos do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-macOS clean #{xcode_action}" + end + + desc "Run unit tests for the current platform built by the Swift Package Manager" + task :swiftpm do |t| + env = { "SWIFT_PACKAGE_TEST_Quick" => "true" } + run env, "swift package clean && swift test" + end +end + +namespace "templates" do + install_dir = File.expand_path("~/Library/Developer/Xcode/Templates/File Templates/Quick") + src_dir = File.expand_path("../Quick Templates", __FILE__) + + desc "Install Quick templates" + task :install do + if File.exists? install_dir + raise "RAKE TASK FAILED: Quick templates are already installed at #{install_dir}" + else + mkdir_p install_dir + cp_r src_dir, install_dir + end + end + + desc "Uninstall Quick templates" + task :uninstall do + rm_rf install_dir + end +end + +if has_xcodebuild then + task default: ["test:ios", "test:tvos", "test:macos"] +else + task default: ["test:swiftpm"] +end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift new file mode 100644 index 0000000..1d98702 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift @@ -0,0 +1,17 @@ +/** + A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` function with a context instance of the generic type. + */ + +open class Behavior { + + open static var name: String { return String(describing: self) } + /** + override this method in your behavior to define a set of reusable examples. + + This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + + - parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject. + */ + open class func spec(_ aContext: @escaping () -> Context) {} +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift new file mode 100644 index 0000000..f5e3711 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift @@ -0,0 +1,45 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _CallsiteBase: NSObject {} + #else + public class _CallsiteBase: NSObject {} + #endif +#else +public class _CallsiteBase: NSObject {} +#endif + +/** + An object encapsulating the file and line number at which + a particular example is defined. +*/ +final public class Callsite: _CallsiteBase { + /** + The absolute path of the file in which an example is defined. + */ + public let file: String + + /** + The line number on which an example is defined. + */ + public let line: UInt + + internal init(file: String, line: UInt) { + self.file = file + self.line = line + } +} + +extension Callsite { + /** + Returns a boolean indicating whether two Callsite objects are equal. + If two callsites are in the same file and on the same line, they must be equal. + */ + @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool { + return lhs.file == rhs.file && lhs.line == rhs.line + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift new file mode 100644 index 0000000..dbb95f1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift @@ -0,0 +1,161 @@ +import Foundation + +/** + A closure that temporarily exposes a Configuration object within + the scope of the closure. +*/ +public typealias QuickConfigurer = (_ configuration: Configuration) -> Void + +/** + A closure that, given metadata about an example, returns a boolean value + indicating whether that example should be run. +*/ +public typealias ExampleFilter = (_ example: Example) -> Bool + +/** + A configuration encapsulates various options you can use + to configure Quick's behavior. +*/ +final public class Configuration: NSObject { + internal let exampleHooks = ExampleHooks() + internal let suiteHooks = SuiteHooks() + internal var exclusionFilters: [ExampleFilter] = [ { example in + if let pending = example.filterFlags[Filter.pending] { + return pending + } else { + return false + } + }] + internal var inclusionFilters: [ExampleFilter] = [ { example in + if let focused = example.filterFlags[Filter.focused] { + return focused + } else { + return false + } + }] + + /** + Run all examples if none match the configured filters. True by default. + */ + public var runAllWhenEverythingFiltered = true + + /** + Registers an inclusion filter. + + All examples are filtered using all inclusion filters. + The remaining examples are run. If no examples remain, all examples are run. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be included in the examples + that are run. + */ + public func include(_ filter: @escaping ExampleFilter) { + inclusionFilters.append(filter) + } + + /** + Registers an exclusion filter. + + All examples that remain after being filtered by the inclusion filters are + then filtered via all exclusion filters. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be excluded from the examples + that are run. + */ + public func exclude(_ filter: @escaping ExampleFilter) { + exclusionFilters.append(filter) + } + + /** + Identical to Quick.Configuration.beforeEach, except the closure is + provided with metadata on the example that the closure is being run + prior to. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(beforeEachWithMetadata:) + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#else + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#endif + + /** + Like Quick.DSL.beforeEach, this configures Quick to execute the + given closure before each example that is run. The closure + passed to this method is executed before each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run before each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which beforeEach closures are evaluated + either. Mulitple beforeEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + exampleHooks.appendBefore(closure) + } + + /** + Identical to Quick.Configuration.afterEach, except the closure + is provided with metadata on the example that the closure is being + run after. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(afterEachWithMetadata:) + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#else + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#endif + + /** + Like Quick.DSL.afterEach, this configures Quick to execute the + given closure after each example that is run. The closure + passed to this method is executed after each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run after each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which afterEach closures are evaluated + either. Mulitple afterEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func afterEach(_ closure: @escaping AfterExampleClosure) { + exampleHooks.appendAfter(closure) + } + + /** + Like Quick.DSL.beforeSuite, this configures Quick to execute + the given closure prior to any and all examples that are run. + The two methods are functionally equivalent. + */ + public func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + /** + Like Quick.DSL.afterSuite, this configures Quick to execute + the given closure after all examples have been run. + The two methods are functionally equivalent. + */ + public func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift new file mode 100644 index 0000000..3da6be2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift @@ -0,0 +1,39 @@ +import Foundation +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE + +open class QuickConfiguration: NSObject { + open class func configure(_ configuration: Configuration) {} +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +internal func qck_enumerateSubclasses(_ klass: T.Type, block: (T.Type) -> Void) { + var classesCount = objc_getClassList(nil, 0) + + guard classesCount > 0 else { + return + } + + let classes = UnsafeMutablePointer.allocate(capacity: Int(classesCount)) + classesCount = objc_getClassList(AutoreleasingUnsafeMutablePointer(classes), classesCount) + + var subclass: AnyClass! + for i in 0.. Void) { + World.sharedWorld.sharedExamples(name) { _ in closure() } +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + - parameter name: The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + - parameter closure: A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + + The closure takes a SharedExampleContext as an argument. This context is a function + that can be executed to retrieve parameters passed in via an `itBehavesLike` function. +*/ +public func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + World.sharedWorld.sharedExamples(name, closure: closure) +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + - parameter description: An arbitrary string describing the example group. + - parameter closure: A closure that can contain other examples. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. +*/ +public func describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.describe(description, flags: flags, closure: closure) +} + +/** + Defines an example group. Equivalent to `describe`. +*/ +public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.context(description, flags: flags, closure: closure) +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run prior to each example. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + World.sharedWorld.beforeEach(closure) +} + +/** + Identical to Quick.DSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + World.sharedWorld.beforeEach(closure: closure) +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run after each example. +*/ +public func afterEach(_ closure: @escaping AfterExampleClosure) { + World.sharedWorld.afterEach(closure) +} + +/** + Identical to Quick.DSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. +*/ +public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + World.sharedWorld.afterEach(closure: closure) +} + +/** + Defines an example. Examples use assertions to demonstrate how code should + behave. These are like "tests" in XCTest. + + - parameter description: An arbitrary string describing what the example is meant to specify. + - parameter closure: A closure that can contain assertions. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the example. A sensible default is provided. + - parameter line: The line containing the example. A sensible default is provided. +*/ +public func it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + itBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + This function also passes those shared examples a context that can be evaluated to give the shared + examples extra information on the subject of the example. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter sharedExampleContext: A closure that, when evaluated, returns key-value pairs that provide the + shared examples with extra information on the subject of the example. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} + +/** + Inserts the examples defined using a `Behavior` into the current example group. + The shared examples are executed at this location, as if they were written out manually. + This function also passes a strongly-typed context that can be evaluated to give the shared examples extra information on the subject of the example. + + - parameter behavior: The type of `Behavior` class defining the example group to be executed. + - parameter context: A closure that, when evaluated, returns an instance of `Behavior`'s context type to provide its example group with extra information on the subject of the example. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. + */ +public func itBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.itBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + - parameter description: An arbitrary string describing the example or example group. + - parameter closure: A closure that will not be evaluated. +*/ +public func pending(_ description: String, closure: () -> Void) { + World.sharedWorld.pending(description, closure: closure) +} + +/** + Use this to quickly mark a `describe` closure as pending. + This disables all examples within the closure. +*/ +public func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + World.sharedWorld.xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark a `context` closure as pending. + This disables all examples within the closure. +*/ +public func xcontext(_ description: String, flags: FilterFlags, closure: () -> Void) { + xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark an `it` closure as pending. + This disables the example and ensures the code within the closure is never run. +*/ +public func xit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.xit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quicklu mark an `itBehavesLike` closure as pending. + This disables the example group defined by this behavior and ensures the code within is never run. +*/ +public func xitBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.xitBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} +/** + Use this to quickly focus a `describe` closure, focusing the examples in the closure. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the closure--they are all treated as focused. +*/ +public func fdescribe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus a `context` closure. Equivalent to `fdescribe`. +*/ +public func fcontext(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus an `it` closure, focusing the example. + If any examples in the test suite are focused, only those examples are executed. +*/ +public func fit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.fit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + fitBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.fitBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} + +/** + Use this to quickly focus on `itBehavesLike` closure. + */ +public func fitBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.fitBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift new file mode 100644 index 0000000..5249027 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift @@ -0,0 +1,205 @@ +import Foundation + +/** + Adds methods to World to support top-level DSL functions (Swift) and + macros (Objective-C). These functions map directly to the DSL that test + writers use in their specs. +*/ +extension World { + internal func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + internal func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } + + internal func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + registerSharedExample(name, closure: closure) + } + + internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'describe' cannot be used inside '\(currentPhase)', 'describe' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleGroup != nil else { + raiseError("Error: example group was not created by its parent QuickSpec spec. Check that describe() or context() was used in QuickSpec.spec() and not a more general context (i.e. an XCTestCase test)") + } + let group = ExampleGroup(description: description, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group, closure: closure) + } + + internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'context' cannot be used inside '\(currentPhase)', 'context' may only be used inside 'context' or 'describe'. ") + } + self.describe(description, flags: flags, closure: closure) + } + + internal func fdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.describe(description, flags: focusedFlags, closure: closure) + } + + internal func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.describe(description, flags: pendingFlags, closure: closure) + } + + internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'beforeEach' cannot be used inside '\(currentPhase)', 'beforeEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendBefore(closure) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(beforeEachWithMetadata:) + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#else + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#endif + + internal func afterEach(_ closure: @escaping AfterExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'afterEach' cannot be used inside '\(currentPhase)', 'afterEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendAfter(closure) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(afterEachWithMetadata:) + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#else + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#endif + + internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + if beforesCurrentlyExecuting { + raiseError("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ") + } + if aftersCurrentlyExecuting { + raiseError("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleMetadata == nil else { + raiseError("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) + currentExampleGroup.appendExample(example) + } + + internal func fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.it(description, flags: focusedFlags, file: file, line: line, closure: closure) + } + + internal func xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.it(description, flags: pendingFlags, file: file, line: line, closure: closure) + } + + internal func itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + guard currentExampleMetadata == nil else { + raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let closure = World.sharedWorld.sharedExample(name) + + let group = ExampleGroup(description: name, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group) { + closure(sharedExampleContext) + } + + group.walkDownExamples { (example: Example) in + example.isSharedExample = true + example.callsite = callsite + } + } + + internal func fitBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: focusedFlags, file: file, line: line) + } + + internal func itBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + guard currentExampleMetadata == nil else { + raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let closure = behavior.spec + let group = ExampleGroup(description: behavior.name, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group) { + closure(context) + } + + group.walkDownExamples { (example: Example) in + example.isSharedExample = true + example.callsite = callsite + } + } + + internal func fitBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.itBehavesLike(behavior, context: context, flags: focusedFlags, file: file, line: line) + } + + internal func xitBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.itBehavesLike(behavior, context: context, flags: pendingFlags, file: file, line: line) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(itWithDescription:flags:file:line:closure:) + private func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + it(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(fitWithDescription:flags:file:line:closure:) + private func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + fit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(xitWithDescription:flags:file:line:closure:) + private func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + xit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:) + private func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) + } +#endif + + internal func pending(_ description: String, closure: () -> Void) { + print("Pending: \(description)") + } + + private var currentPhase: String { + if beforesCurrentlyExecuting { + return "beforeEach" + } else if aftersCurrentlyExecuting { + return "afterEach" + } + + return "it" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift new file mode 100644 index 0000000..155fefd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +internal func raiseError(_ message: String) -> Never { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise() +#endif + + // This won't be reached when ObjC is available and the exception above is raisd + fatalError(message) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Example.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Example.swift new file mode 100644 index 0000000..c15b31a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Example.swift @@ -0,0 +1,131 @@ +import Foundation + +private var numberOfExamplesRun = 0 +private var numberOfIncludedExamples = 0 + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _ExampleBase: NSObject {} + #else + public class _ExampleBase: NSObject {} + #endif +#else +public class _ExampleBase: NSObject {} +#endif + +/** + Examples, defined with the `it` function, use assertions to + demonstrate how code should behave. These are like "tests" in XCTest. +*/ +final public class Example: _ExampleBase { + /** + A boolean indicating whether the example is a shared example; + i.e.: whether it is an example defined with `itBehavesLike`. + */ + public var isSharedExample = false + + /** + The site at which the example is defined. + This must be set correctly in order for Xcode to highlight + the correct line in red when reporting a failure. + */ + public var callsite: Callsite + + weak internal var group: ExampleGroup? + + private let internalDescription: String + private let closure: () -> Void + private let flags: FilterFlags + + internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: @escaping () -> Void) { + self.internalDescription = description + self.closure = closure + self.callsite = callsite + self.flags = flags + } + + public override var description: String { + return internalDescription + } + + /** + The example name. A name is a concatenation of the name of + the example group the example belongs to, followed by the + description of the example itself. + + The example name is used to generate a test method selector + to be displayed in Xcode's test navigator. + */ + public var name: String { + guard let groupName = group?.name else { return description } + return "\(groupName), \(description)" + } + + /** + Executes the example closure, as well as all before and after + closures defined in the its surrounding example groups. + */ + public func run() { + let world = World.sharedWorld + + if numberOfIncludedExamples == 0 { + numberOfIncludedExamples = world.includedExampleCount + } + + if numberOfExamplesRun == 0 { + world.suiteHooks.executeBefores() + } + + let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun) + world.currentExampleMetadata = exampleMetadata + + world.exampleHooks.executeBefores(exampleMetadata) + group!.phase = .beforesExecuting + for before in group!.befores { + before(exampleMetadata) + } + group!.phase = .beforesFinished + + closure() + + group!.phase = .aftersExecuting + for after in group!.afters { + after(exampleMetadata) + } + group!.phase = .aftersFinished + world.exampleHooks.executeAfters(exampleMetadata) + + numberOfExamplesRun += 1 + + if !world.isRunningAdditionalSuites && numberOfExamplesRun >= numberOfIncludedExamples { + world.suiteHooks.executeAfters() + } + } + + /** + Evaluates the filter flags set on this example and on the example groups + this example belongs to. Flags set on the example are trumped by flags on + the example group it belongs to. Flags on inner example groups are trumped + by flags on outer example groups. + */ + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + for (key, value) in group!.filterFlags { + aggregateFlags[key] = value + } + return aggregateFlags + } +} + +extension Example { + /** + Returns a boolean indicating whether two Example objects are equal. + If two examples are defined at the exact same callsite, they must be equal. + */ + @nonobjc public static func == (lhs: Example, rhs: Example) -> Bool { + return lhs.callsite == rhs.callsite + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift new file mode 100644 index 0000000..129bed0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift @@ -0,0 +1,99 @@ +import Foundation + +/** + Example groups are logical groupings of examples, defined with + the `describe` and `context` functions. Example groups can share + setup and teardown code. +*/ +final public class ExampleGroup: NSObject { + weak internal var parent: ExampleGroup? + internal let hooks = ExampleHooks() + + internal var phase: HooksPhase = .nothingExecuted + + private let internalDescription: String + private let flags: FilterFlags + private let isInternalRootExampleGroup: Bool + private var childGroups = [ExampleGroup]() + private var childExamples = [Example]() + + internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) { + self.internalDescription = description + self.flags = flags + self.isInternalRootExampleGroup = isInternalRootExampleGroup + } + + public override var description: String { + return internalDescription + } + + /** + Returns a list of examples that belong to this example group, + or to any of its descendant example groups. + */ + public var examples: [Example] { + return childExamples + childGroups.flatMap { $0.examples } + } + + internal var name: String? { + guard let parent = parent else { + return isInternalRootExampleGroup ? nil : description + } + + guard let name = parent.name else { return description } + return "\(name), \(description)" + } + + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + walkUp { group in + for (key, value) in group.flags { + aggregateFlags[key] = value + } + } + return aggregateFlags + } + + internal var befores: [BeforeExampleWithMetadataClosure] { + var closures = Array(hooks.befores.reversed()) + walkUp { group in + closures.append(contentsOf: Array(group.hooks.befores.reversed())) + } + return Array(closures.reversed()) + } + + internal var afters: [AfterExampleWithMetadataClosure] { + var closures = hooks.afters + walkUp { group in + closures.append(contentsOf: group.hooks.afters) + } + return closures + } + + internal func walkDownExamples(_ callback: (_ example: Example) -> Void) { + for example in childExamples { + callback(example) + } + for group in childGroups { + group.walkDownExamples(callback) + } + } + + internal func appendExampleGroup(_ group: ExampleGroup) { + group.parent = self + childGroups.append(group) + } + + internal func appendExample(_ example: Example) { + example.group = self + childExamples.append(example) + } + + private func walkUp(_ callback: (_ group: ExampleGroup) -> Void) { + var group = self + while let parent = group.parent { + callback(parent) + group = parent + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift new file mode 100644 index 0000000..3dd28ab --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift @@ -0,0 +1,37 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _ExampleMetadataBase: NSObject {} + #else + public class _ExampleMetadataBase: NSObject {} + #endif +#else +public class _ExampleMetadataBase: NSObject {} +#endif + +/** + A class that encapsulates information about an example, + including the index at which the example was executed, as + well as the example itself. +*/ +final public class ExampleMetadata: _ExampleMetadataBase { + /** + The example for which this metadata was collected. + */ + public let example: Example + + /** + The index at which this example was executed in the + test suite. + */ + public let exampleIndex: Int + + internal init(example: Example, exampleIndex: Int) { + self.example = example + self.exampleIndex = exampleIndex + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift new file mode 100644 index 0000000..da137f8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift @@ -0,0 +1,44 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _FilterBase: NSObject {} + #else + public class _FilterBase: NSObject {} + #endif +#else +public class _FilterBase: NSObject {} +#endif + +/** + A mapping of string keys to booleans that can be used to + filter examples or example groups. For example, a "focused" + example would have the flags [Focused: true]. +*/ +public typealias FilterFlags = [String: Bool] + +/** + A namespace for filter flag keys, defined primarily to make the + keys available in Objective-C. +*/ +final public class Filter: _FilterBase { + /** + Example and example groups with [Focused: true] are included in test runs, + excluding all other examples without this flag. Use this to only run one or + two tests that you're currently focusing on. + */ + public class var focused: String { + return "focused" + } + + /** + Example and example groups with [Pending: true] are excluded from test runs. + Use this to temporarily suspend examples that you know do not pass yet. + */ + public class var pending: String { + return "pending" + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift new file mode 100644 index 0000000..9c7d310 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift @@ -0,0 +1,35 @@ +// MARK: Example Hooks + +/** + A closure executed before an example is run. +*/ +public typealias BeforeExampleClosure = () -> Void + +/** + A closure executed before an example is run. The closure is given example metadata, + which contains information about the example that is about to be run. +*/ +public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void + +/** + A closure executed after an example is run. +*/ +public typealias AfterExampleClosure = BeforeExampleClosure + +/** + A closure executed after an example is run. The closure is given example metadata, + which contains information about the example that has just finished running. +*/ +public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure + +// MARK: Suite Hooks + +/** + A closure executed before any examples are run. +*/ +public typealias BeforeSuiteClosure = () -> Void + +/** + A closure executed after all examples have finished running. +*/ +public typealias AfterSuiteClosure = BeforeSuiteClosure diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift new file mode 100644 index 0000000..449cbfc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift @@ -0,0 +1,42 @@ +/** + A container for closures to be executed before and after each example. +*/ +final internal class ExampleHooks { + internal var befores: [BeforeExampleWithMetadataClosure] = [] + internal var afters: [AfterExampleWithMetadataClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) { + befores.append(closure) + } + + internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { + befores.append { (_: ExampleMetadata) in closure() } + } + + internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) { + afters.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterExampleClosure) { + afters.append { (_: ExampleMetadata) in closure() } + } + + internal func executeBefores(_ exampleMetadata: ExampleMetadata) { + phase = .beforesExecuting + for before in befores { + before(exampleMetadata) + } + + phase = .beforesFinished + } + + internal func executeAfters(_ exampleMetadata: ExampleMetadata) { + phase = .aftersExecuting + for after in afters { + after(exampleMetadata) + } + + phase = .aftersFinished + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift new file mode 100644 index 0000000..2440158 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift @@ -0,0 +1,11 @@ +/** + A description of the execution cycle of the current example with + respect to the hooks of that example. + */ +internal enum HooksPhase { + case nothingExecuted + case beforesExecuting + case beforesFinished + case aftersExecuting + case aftersFinished +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift new file mode 100644 index 0000000..b39292b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift @@ -0,0 +1,32 @@ +/** + A container for closures to be executed before and after all examples. +*/ +final internal class SuiteHooks { + internal var befores: [BeforeSuiteClosure] = [] + internal var afters: [AfterSuiteClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) { + befores.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterSuiteClosure) { + afters.append(closure) + } + + internal func executeBefores() { + phase = .beforesExecuting + for before in befores { + before() + } + phase = .beforesFinished + } + + internal func executeAfters() { + phase = .aftersExecuting + for after in afters { + after() + } + phase = .aftersFinished + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Info.plist new file mode 100644 index 0000000..9667430 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 - present, Quick Team. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift new file mode 100644 index 0000000..d7a1442 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift @@ -0,0 +1,25 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + +import Foundation + +extension Bundle { + + /** + Locates the first bundle with a '.xctest' file extension. + */ + internal static var currentTestBundle: Bundle? { + return allBundles.first { $0.bundlePath.hasSuffix(".xctest") } + } + + /** + Return the module name of the bundle. + Uses the bundle filename and transform it to match Xcode's transformation. + Module name has to be a valid "C99 extended identifier". + */ + internal var moduleName: String { + let fileName = bundleURL.fileName as NSString + return fileName.c99ExtendedIdentifier + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift new file mode 100644 index 0000000..ef73762 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift @@ -0,0 +1,33 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +public extension NSString { + + private static var invalidCharacters: CharacterSet = { + var invalidCharacters = CharacterSet() + + let invalidCharacterSets: [CharacterSet] = [ + .whitespacesAndNewlines, + .illegalCharacters, + .controlCharacters, + .punctuationCharacters, + .nonBaseCharacters, + .symbols + ] + + for invalidSet in invalidCharacterSets { + invalidCharacters.formUnion(invalidSet) + } + + return invalidCharacters + }() + + @objc(qck_c99ExtendedIdentifier) + var c99ExtendedIdentifier: String { + let validComponents = components(separatedBy: NSString.invalidCharacters) + let result = validComponents.joined(separator: "_") + + return result.isEmpty ? "_" : result + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift new file mode 100644 index 0000000..eb9aba5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift @@ -0,0 +1,38 @@ +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE && os(Linux) + +/// When using Quick with swift-corelibs-xctest, automatic discovery of specs and +/// configurations is not available. Instead, you should create a standalone +/// executable and call this function from its main.swift file. This will execute +/// the specs and then terminate the process with an exit code of 0 if the tests +/// passed, or 1 if there were any failures. +/// +/// Quick is known to work with the DEVELOPMENT-SNAPSHOT-2016-02-08-a Swift toolchain. +/// +/// - parameter specs: An array of QuickSpec subclasses to run +/// - parameter configurations: An array QuickConfiguration subclasses for setting up +// global suite configuration (optional) +/// - parameter testCases: An array of XCTestCase test cases, just as would be passed +/// info `XCTMain` if you were using swift-corelibs-xctest directly. +/// This allows for mixing Quick specs and XCTestCase tests in one run. +public func QCKMain(_ specs: [QuickSpec.Type], + configurations: [QuickConfiguration.Type] = [], + testCases: [XCTestCaseEntry] = []) -> Never { + let world = World.sharedWorld + + // Perform all configurations (ensures that shared examples have been discovered) + world.configure { configuration in + for configurationClass in configurations { + configurationClass.configure(configuration) + } + } + world.finalizeConfiguration() + + XCTMain(specs.flatMap { testCase($0.allTests) } + testCases) +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift new file mode 100644 index 0000000..415b680 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift @@ -0,0 +1,74 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +/** + Responsible for building a "Selected tests" suite. This corresponds to a single + spec, and all its examples. + */ +internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder { + + /** + The test spec class to run. + */ + let testCaseClass: AnyClass! + + /** + For Objective-C classes, returns the class name. For Swift classes without, + an explicit Objective-C name, returns a module-namespaced class name + (e.g., "FooTests.FooSpec"). + */ + var testSuiteClassName: String { + return NSStringFromClass(testCaseClass) + } + + /** + Given a test case name: + + FooSpec/testFoo + + Optionally constructs a test suite builder for the named test case class + in the running test bundle. + + If no test bundle can be found, or the test case class can't be found, + initialization fails and returns `nil`. + */ + init?(forTestCaseWithName name: String) { + guard let testCaseClass = testCaseClassForTestCaseWithName(name) else { + self.testCaseClass = nil + return nil + } + + self.testCaseClass = testCaseClass + } + + /** + Returns a `QuickTestSuite` that runs the associated test case class. + */ + func buildTestSuite() -> QuickTestSuite { + return QuickTestSuite(forTestCaseClass: testCaseClass) + } + +} + +/** + Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named + test case class in that bundle. + + Returns `nil` if a bundle or test case class cannot be found. + */ +private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? { + func extractClassName(_ name: String) -> String? { + return name.components(separatedBy: "/").first + } + + guard let className = extractClassName(name) else { return nil } + guard let bundle = Bundle.currentTestBundle else { return nil } + + if let testCaseClass = bundle.classNamed(className) { return testCaseClass } + + let moduleName = bundle.moduleName + + return NSClassFromString("\(moduleName).\(className)") +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift new file mode 100644 index 0000000..12845d8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift @@ -0,0 +1,134 @@ +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +import QuickSpecBase + +public typealias QuickSpecBase = _QuickSpecBase +#else +public typealias QuickSpecBase = XCTestCase +#endif + +open class QuickSpec: QuickSpecBase { + open func spec() {} + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + public required init() { + super.init(name: "", testClosure: { _ in }) + } + public required init(name: String, testClosure: @escaping (XCTestCase) throws -> Swift.Void) { + super.init(name: name, testClosure: testClosure) + } +#else + public required override init() { + super.init() + } + + /// This method is used as a hook for the following two purposes + /// + /// 1. Performing all configurations + /// 2. Gathering examples for each spec classes + /// + /// On Linux, those are done in `LinuxMain.swift` and `Quick.QCKMain`. But + /// SwiftPM on macOS does not have the mechanism (test cases are automatically + /// discovered powered by Objective-C runtime), so we needed the alternative + /// way. + #if swift(>=4) + override open class var defaultTestSuite: XCTestSuite { + configureDefaultTestSuite() + + return super.defaultTestSuite + } + #else + override open class func defaultTestSuite() -> XCTestSuite { + configureDefaultTestSuite() + + return super.defaultTestSuite() + } + #endif + + private static func configureDefaultTestSuite() { + let world = World.sharedWorld + + if !world.isConfigurationFinalized { + // Perform all configurations (ensures that shared examples have been discovered) + world.configure { configuration in + qck_enumerateSubclasses(QuickConfiguration.self) { configurationClass in + configurationClass.configure(configuration) + } + } + world.finalizeConfiguration() + } + + // Let's gather examples for each spec classes. This has the same effect + // as listing spec classes in `LinuxMain.swift` on Linux. + _ = allTests + } + + override open class func _qck_testMethodSelectors() -> [_QuickSelectorWrapper] { + let examples = World.sharedWorld.examples(self) + + var selectorNames = Set() + return examples.map { example in + let selector = addInstanceMethod(for: example, classSelectorNames: &selectorNames) + return _QuickSelectorWrapper(selector: selector) + } + } + + private static func addInstanceMethod(for example: Example, classSelectorNames selectorNames : inout Set) -> Selector { + let block: @convention(block) (QuickSpec) -> Void = { _ in + example.run() + } + let implementation = imp_implementationWithBlock(block as Any) + + let originalName = example.name + var selectorName = originalName + var i: UInt = 2 + + while selectorNames.contains(selectorName) { + selectorName = String(format: "%@_%tu", originalName, i) + i += 1 + } + + selectorNames.insert(selectorName) + + let selector = NSSelectorFromString(selectorName) + class_addMethod(self, selector, implementation, "v@:") + + return selector + } +#endif + + static var allTestsCache = [String: [(String, (XCTestCase) -> () throws -> Void)]]() + + public class var allTests: [(String, (XCTestCase) -> () throws -> Void)] { + if let cached = allTestsCache[String(describing: self)] { + return cached + } + + gatherExamplesIfNeeded() + + let examples = World.sharedWorld.examples(self) + let result = examples.map { example -> (String, (XCTestCase) -> () throws -> Void) in + return (example.name, { _ in { example.run() } }) + } + allTestsCache[String(describing: self)] = result + return result + } + + internal static func gatherExamplesIfNeeded() { + let world = World.sharedWorld + let rootExampleGroup = world.rootExampleGroupForSpecClass(self) + if rootExampleGroup.examples.isEmpty { + world.currentExampleGroup = rootExampleGroup + self.init().spec() + world.currentExampleGroup = nil + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift new file mode 100644 index 0000000..0fe76a7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift @@ -0,0 +1,52 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + +import XCTest + +/** + This protocol defines the role of an object that builds test suites. + */ +internal protocol QuickTestSuiteBuilder { + + /** + Construct a `QuickTestSuite` instance with the appropriate test cases added as tests. + + Subsequent calls to this method should return equivalent test suites. + */ + func buildTestSuite() -> QuickTestSuite + +} + +/** + A base class for a class cluster of Quick test suites, that should correctly + build dynamic test suites for XCTest to execute. + */ +public class QuickTestSuite: XCTestSuite { + + private static var builtTestSuites: Set = Set() + + /** + Construct a test suite for a specific, selected subset of test cases (rather + than the default, which as all test cases). + + If this method is called multiple times for the same test case class, e.g.. + + FooSpec/testFoo + FooSpec/testBar + + It is expected that the first call should return a valid test suite, and + all subsequent calls should return `nil`. + */ + @objc + public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { + guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } + + let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName) + if inserted { + return builder.buildTestSuite() + } else { + return nil + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift new file mode 100644 index 0000000..23c4781 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift @@ -0,0 +1,12 @@ +import Foundation + +extension URL { + + /** + Returns the path file name without file extension. + */ + var fileName: String { + return self.deletingPathExtension().lastPathComponent + } + +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/World.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/World.swift new file mode 100644 index 0000000..127239a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/Quick/World.swift @@ -0,0 +1,247 @@ +import Foundation + +/** + A closure that, when evaluated, returns a dictionary of key-value + pairs that can be accessed from within a group of shared examples. +*/ +public typealias SharedExampleContext = () -> [String: Any] + +/** + A closure that is used to define a group of shared examples. This + closure may contain any number of example and example groups. +*/ +public typealias SharedExampleClosure = (@escaping SharedExampleContext) -> Void + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + internal class _WorldBase: NSObject {} + #else + internal class _WorldBase: NSObject {} + #endif +#else +internal class _WorldBase: NSObject {} +#endif + +/** + A collection of state Quick builds up in order to work its magic. + World is primarily responsible for maintaining a mapping of QuickSpec + classes to root example groups for those classes. + + It also maintains a mapping of shared example names to shared + example closures. + + You may configure how Quick behaves by calling the -[World configure:] + method from within an overridden +[QuickConfiguration configure:] method. +*/ +final internal class World: _WorldBase { + /** + The example group that is currently being run. + The DSL requires that this group is correctly set in order to build a + correct hierarchy of example groups and their examples. + */ + internal var currentExampleGroup: ExampleGroup! + + /** + The example metadata of the test that is currently being run. + This is useful for using the Quick test metadata (like its name) at + runtime. + */ + + internal var currentExampleMetadata: ExampleMetadata? + + /** + A flag that indicates whether additional test suites are being run + within this test suite. This is only true within the context of Quick + functional tests. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // Convention of generating Objective-C selector has been changed on Swift 3 + @objc(isRunningAdditionalSuites) + internal var isRunningAdditionalSuites = false +#else + internal var isRunningAdditionalSuites = false +#endif + + private var specs: [String: ExampleGroup] = [:] + private var sharedExamples: [String: SharedExampleClosure] = [:] + private let configuration = Configuration() + + internal private(set) var isConfigurationFinalized = false + + internal var exampleHooks: ExampleHooks {return configuration.exampleHooks } + internal var suiteHooks: SuiteHooks { return configuration.suiteHooks } + + // MARK: Singleton Constructor + + private override init() {} + + static let sharedWorld = World() + + // MARK: Public Interface + + /** + Exposes the World's Configuration object within the scope of the closure + so that it may be configured. This method must not be called outside of + an overridden +[QuickConfiguration configure:] method. + + - parameter closure: A closure that takes a Configuration object that can + be mutated to change Quick's behavior. + */ + internal func configure(_ closure: QuickConfigurer) { + assert(!isConfigurationFinalized, + "Quick cannot be configured outside of a +[QuickConfiguration configure:] method. You should not call -[World configure:] directly. Instead, subclass QuickConfiguration and override the +[QuickConfiguration configure:] method.") + closure(configuration) + } + + /** + Finalizes the World's configuration. + Any subsequent calls to World.configure() will raise. + */ + internal func finalizeConfiguration() { + isConfigurationFinalized = true + } + + /** + Returns an internally constructed root example group for the given + QuickSpec class. + + A root example group with the description "root example group" is lazily + initialized for each QuickSpec class. This root example group wraps the + top level of a -[QuickSpec spec] method--it's thanks to this group that + users can define beforeEach and it closures at the top level, like so: + + override func spec() { + // These belong to the root example group + beforeEach {} + it("is at the top level") {} + } + + - parameter cls: The QuickSpec class for which to retrieve the root example group. + - returns: The root example group for the class. + */ + internal func rootExampleGroupForSpecClass(_ cls: AnyClass) -> ExampleGroup { + let name = String(describing: cls) + + if let group = specs[name] { + return group + } else { + let group = ExampleGroup( + description: "root example group", + flags: [:], + isInternalRootExampleGroup: true + ) + specs[name] = group + return group + } + } + + /** + Returns all examples that should be run for a given spec class. + There are two filtering passes that occur when determining which examples should be run. + That is, these examples are the ones that are included by inclusion filters, and are + not excluded by exclusion filters. + + - parameter specClass: The QuickSpec subclass for which examples are to be returned. + - returns: A list of examples to be run as test invocations. + */ + internal func examples(_ specClass: AnyClass) -> [Example] { + // 1. Grab all included examples. + let included = includedExamples + // 2. Grab the intersection of (a) examples for this spec, and (b) included examples. + let spec = rootExampleGroupForSpecClass(specClass).examples.filter { included.contains($0) } + // 3. Remove all excluded examples. + return spec.filter { example in + !self.configuration.exclusionFilters.reduce(false) { $0 || $1(example) } + } + } + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(examplesForSpecClass:) + private func objc_examples(_ specClass: AnyClass) -> [Example] { + return examples(specClass) + } +#endif + + // MARK: Internal + + internal func registerSharedExample(_ name: String, closure: @escaping SharedExampleClosure) { + raiseIfSharedExampleAlreadyRegistered(name) + sharedExamples[name] = closure + } + + internal func sharedExample(_ name: String) -> SharedExampleClosure { + raiseIfSharedExampleNotRegistered(name) + return sharedExamples[name]! + } + + internal var includedExampleCount: Int { + return includedExamples.count + } + + internal var beforesCurrentlyExecuting: Bool { + let suiteBeforesExecuting = suiteHooks.phase == .beforesExecuting + let exampleBeforesExecuting = exampleHooks.phase == .beforesExecuting + var groupBeforesExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupBeforesExecuting = runningExampleGroup.phase == .beforesExecuting + } + + return suiteBeforesExecuting || exampleBeforesExecuting || groupBeforesExecuting + } + + internal var aftersCurrentlyExecuting: Bool { + let suiteAftersExecuting = suiteHooks.phase == .aftersExecuting + let exampleAftersExecuting = exampleHooks.phase == .aftersExecuting + var groupAftersExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupAftersExecuting = runningExampleGroup.phase == .aftersExecuting + } + + return suiteAftersExecuting || exampleAftersExecuting || groupAftersExecuting + } + + internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { + let previousExampleGroup = currentExampleGroup + currentExampleGroup = group + + closure() + + currentExampleGroup = previousExampleGroup + } + + private var allExamples: [Example] { + var all: [Example] = [] + for (_, group) in specs { + group.walkDownExamples { all.append($0) } + } + return all + } + + private var includedExamples: [Example] { + let all = allExamples + let included = all.filter { example in + return self.configuration.inclusionFilters.reduce(false) { $0 || $1(example) } + } + + if included.isEmpty && configuration.runAllWhenEverythingFiltered { + return all + } else { + return included + } + } + + private func raiseIfSharedExampleAlreadyRegistered(_ name: String) { + if sharedExamples[name] != nil { + raiseError("A shared example named '\(name)' has already been registered.") + } + } + + private func raiseIfSharedExampleNotRegistered(_ name: String) { + if sharedExamples[name] == nil { + raiseError("No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(sharedExamples.keys))'") + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h new file mode 100644 index 0000000..5646199 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h @@ -0,0 +1,30 @@ +#import + +@class Configuration; + +/** + Subclass QuickConfiguration and override the +[QuickConfiguration configure:] + method in order to configure how Quick behaves when running specs, or to define + shared examples that are used across spec files. + */ +@interface QuickConfiguration : NSObject + +/** + This method is executed on each subclass of this class before Quick runs + any examples. You may override this method on as many subclasses as you like, but + there is no guarantee as to the order in which these methods are executed. + + You can override this method in order to: + + 1. Configure how Quick behaves, by modifying properties on the Configuration object. + Setting the same properties in several methods has undefined behavior. + + 2. Define shared examples using `sharedExamples`. + + @param configuration A mutable object that is used to configure how Quick behaves on + a framework level. For details on all the options, see the + documentation in Configuration.swift. + */ ++ (void)configure:(Configuration *)configuration; + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m new file mode 100644 index 0000000..937b818 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m @@ -0,0 +1,83 @@ +#import "QuickConfiguration.h" +#import "World.h" +#import + +typedef void (^QCKClassEnumerationBlock)(Class klass); + +/** + Finds all direct subclasses of the given class and passes them to the block provided. + The classes are iterated over in the order that objc_getClassList returns them. + + @param klass The base class to find subclasses of. + @param block A block that takes a Class. This block will be executed once for each subclass of klass. + */ +void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) { + Class *classes = NULL; + int classesCount = objc_getClassList(NULL, 0); + + if (classesCount > 0) { + classes = (Class *)calloc(sizeof(Class), classesCount); + classesCount = objc_getClassList(classes, classesCount); + + Class subclass, superclass; + for(int i = 0; i < classesCount; i++) { + subclass = classes[i]; + superclass = class_getSuperclass(subclass); + if (superclass == klass && block) { + block(subclass); + } + } + + free(classes); + } +} + +@implementation QuickConfiguration + +#pragma mark - Object Lifecycle + +/** + QuickConfiguration is not meant to be instantiated; it merely provides a hook + for users to configure how Quick behaves. Raise an exception if an instance of + QuickConfiguration is created. + */ +- (instancetype)init { + NSString *className = NSStringFromClass([self class]); + NSString *selectorName = NSStringFromSelector(@selector(configure:)); + [NSException raise:NSInternalInconsistencyException + format:@"%@ is not meant to be instantiated; " + @"subclass %@ and override %@ to configure Quick.", + className, className, selectorName]; + return nil; +} + +#pragma mark - NSObject Overrides + +/** + Hook into when QuickConfiguration is initialized in the runtime in order to + call +[QuickConfiguration configure:] on each of its subclasses. + */ ++ (void)initialize { + // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. + if ([self class] == [QuickConfiguration class]) { + + // Only enumerate over subclasses once, even if +[QuickConfiguration initialize] + // were to be called several times. This is necessary because +[QuickSpec initialize] + // manually calls +[QuickConfiguration initialize]. + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) { + [[World sharedWorld] configure:^(Configuration *configuration) { + [klass configure:configuration]; + }]; + }); + [[World sharedWorld] finalizeConfiguration]; + }); + } +} + +#pragma mark - Public Interface + ++ (void)configure:(Configuration *)configuration { } + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h new file mode 100644 index 0000000..c5f3152 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h @@ -0,0 +1,234 @@ +#import + +@class ExampleMetadata; + +/** + Provides a hook for Quick to be configured before any examples are run. + Within this scope, override the +[QuickConfiguration configure:] method + to set properties on a configuration object to customize Quick behavior. + For details, see the documentation for Configuraiton.swift. + + @param name The name of the configuration class. Like any Objective-C + class name, this must be unique to the current runtime + environment. + */ +#define QuickConfigurationBegin(name) \ + @interface name : QuickConfiguration; @end \ + @implementation name \ + + +/** + Marks the end of a Quick configuration. + Make sure you put this after `QuickConfigurationBegin`. + */ +#define QuickConfigurationEnd \ + @end \ + + +/** + Defines a new QuickSpec. Define examples and example groups within the space + between this and `QuickSpecEnd`. + + @param name The name of the spec class. Like any Objective-C class name, this + must be unique to the current runtime environment. + */ +#define QuickSpecBegin(name) \ + @interface name : QuickSpec; @end \ + @implementation name \ + - (void)spec { \ + + +/** + Marks the end of a QuickSpec. Make sure you put this after `QuickSpecBegin`. + */ +#define QuickSpecEnd \ + } \ + @end \ + +typedef NSDictionary *(^QCKDSLSharedExampleContext)(void); +typedef void (^QCKDSLSharedExampleBlock)(QCKDSLSharedExampleContext); +typedef void (^QCKDSLEmptyBlock)(void); +typedef void (^QCKDSLExampleMetadataBlock)(ExampleMetadata *exampleMetadata); + +#define QUICK_EXPORT FOUNDATION_EXPORT + +QUICK_EXPORT void qck_beforeSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure); +QUICK_EXPORT void qck_describe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_context(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_afterEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_pending(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure); + +#ifndef QUICK_DISABLE_SHORT_SYNTAX +/** + Defines a closure to be run prior to any examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before the first example is run, this closure + will not be executed. + + @param closure The closure to be run prior to any examples in the test suite. + */ +static inline void beforeSuite(QCKDSLEmptyBlock closure) { + qck_beforeSuite(closure); +} + + +/** + Defines a closure to be run after all of the examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before all examples are run, this closure + will not be executed. + + @param closure The closure to be run after all of the examples in the test suite. + */ +static inline void afterSuite(QCKDSLEmptyBlock closure) { + qck_afterSuite(closure); +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + @param name The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + @param closure A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + */ +static inline void sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + qck_sharedExamples(name, closure); +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + @param description An arbitrary string describing the example group. + @param closure A closure that can contain other examples. + */ +static inline void describe(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +/** + Defines an example group. Equivalent to `describe`. + */ +static inline void context(NSString *description, QCKDSLEmptyBlock closure) { + qck_context(description, closure); +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run prior to each example. + */ +static inline void beforeEach(QCKDSLEmptyBlock closure) { + qck_beforeEach(closure); +} + +/** + Identical to QCKDSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. + */ +static inline void beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_beforeEachWithMetadata(closure); +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run after each example. + */ +static inline void afterEach(QCKDSLEmptyBlock closure) { + qck_afterEach(closure); +} + +/** + Identical to QCKDSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. + */ +static inline void afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_afterEachWithMetadata(closure); +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + @param description An arbitrary string describing the example or example group. + @param closure A closure that will not be evaluated. + */ +static inline void pending(NSString *description, QCKDSLEmptyBlock closure) { + qck_pending(description, closure); +} + +/** + Use this to quickly mark a `describe` block as pending. + This disables all examples within the block. + */ +static inline void xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +/** + Use this to quickly mark a `context` block as pending. + This disables all examples within the block. + */ +static inline void xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xcontext(description, closure); +} + +/** + Use this to quickly focus a `describe` block, focusing the examples in the block. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the block--they are all treated as focused. + */ +static inline void fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} + +/** + Use this to quickly focus a `context` block. Equivalent to `fdescribe`. + */ +static inline void fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fcontext(description, closure); +} + +#define it qck_it +#define xit qck_xit +#define fit qck_fit +#define itBehavesLike qck_itBehavesLike +#define xitBehavesLike qck_xitBehavesLike +#define fitBehavesLike qck_fitBehavesLike +#endif + +#define qck_it qck_it_builder(@{}, @(__FILE__), __LINE__) +#define qck_xit qck_it_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fit qck_it_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) +#define qck_itBehavesLike qck_itBehavesLike_builder(@{}, @(__FILE__), __LINE__) +#define qck_xitBehavesLike qck_itBehavesLike_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fitBehavesLike qck_itBehavesLike_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) + +typedef void (^QCKItBlock)(NSString *description, QCKDSLEmptyBlock closure); +typedef void (^QCKItBehavesLikeBlock)(NSString *description, QCKDSLSharedExampleContext context); + +QUICK_EXPORT QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line); +QUICK_EXPORT QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m new file mode 100644 index 0000000..10e8a3d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m @@ -0,0 +1,79 @@ +#import "QCKDSL.h" +#import "World.h" +#import "World+DSL.h" + +void qck_beforeSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeSuite:closure]; +} + +void qck_afterSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterSuite:closure]; +} + +void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + [[World sharedWorld] sharedExamples:name closure:closure]; +} + +void qck_describe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] describe:description flags:@{} closure:closure]; +} + +void qck_context(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +void qck_beforeEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeEach:closure]; +} + +void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] beforeEachWithMetadata:closure]; +} + +void qck_afterEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterEach:closure]; +} + +void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] afterEachWithMetadata:closure]; +} + +QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] itWithDescription:description + flags:flags + file:file + line:line + closure:closure]; + }; +} + +QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *name, QCKDSLSharedExampleContext context) { + [[World sharedWorld] itBehavesLikeSharedExampleNamed:name + sharedExampleContext:context + flags:flags + file:file + line:line]; + }; +} + +void qck_pending(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] pending:description closure:closure]; +} + +void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] xdescribe:description flags:@{} closure:closure]; +} + +void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] fdescribe:description flags:@{} closure:closure]; +} + +void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h new file mode 100644 index 0000000..9f528ec --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h @@ -0,0 +1,24 @@ +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +@interface World (SWIFT_EXTENSION(Quick)) +- (void)beforeSuite:(void (^ __nonnull)(void))closure; +- (void)afterSuite:(void (^ __nonnull)(void))closure; +- (void)sharedExamples:(NSString * __nonnull)name closure:(void (^ __nonnull)(NSDictionary * __nonnull (^ __nonnull)(void)))closure; +- (void)describe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)context:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)fdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)xdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)beforeEach:(void (^ __nonnull)(void))closure; +- (void)beforeEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure; +- (void)afterEach:(void (^ __nonnull)(void))closure; +- (void)afterEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure; +- (void)itWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)fitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)xitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)itBehavesLikeSharedExampleNamed:(NSString * __nonnull)name sharedExampleContext:(NSDictionary * __nonnull (^ __nonnull)(void))sharedExampleContext flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line; +- (void)pending:(NSString * __nonnull)description closure:(void (^ __nonnull)(void))closure; +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h new file mode 100644 index 0000000..87dad10 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h @@ -0,0 +1,11 @@ +#import + +//! Project version number for Quick. +FOUNDATION_EXPORT double QuickVersionNumber; + +//! Project version string for Quick. +FOUNDATION_EXPORT const unsigned char QuickVersionString[]; + +#import "QuickSpec.h" +#import "QCKDSL.h" +#import "QuickConfiguration.h" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h new file mode 100644 index 0000000..21bc772 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h @@ -0,0 +1,56 @@ +#import + +/** + QuickSpec is a base class all specs written in Quick inherit from. + They need to inherit from QuickSpec, a subclass of XCTestCase, in + order to be discovered by the XCTest framework. + + XCTest automatically compiles a list of XCTestCase subclasses included + in the test target. It iterates over each class in that list, and creates + a new instance of that class for each test method. It then creates an + "invocation" to execute that test method. The invocation is an instance of + NSInvocation, which represents a single message send in Objective-C. + The invocation is set on the XCTestCase instance, and the test is run. + + Most of the code in QuickSpec is dedicated to hooking into XCTest events. + First, when the spec is first loaded and before it is sent any messages, + the +[NSObject initialize] method is called. QuickSpec overrides this method + to call +[QuickSpec spec]. This builds the example group stacks and + registers them with Quick.World, a global register of examples. + + Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest + automatically finds all methods whose selectors begin with the string "test". + However, QuickSpec overrides this default behavior by implementing the + +[XCTestCase testInvocations] method. This method iterates over each example + registered in Quick.World, defines a new method for that example, and + returns an invocation to call that method to XCTest. Those invocations are + the tests that are run by XCTest. Their selector names are displayed in + the Xcode test navigation bar. + */ +@interface QuickSpec : XCTestCase + +/** + Override this method in your spec to define a set of example groups + and examples. + + @code + override func spec() { + describe("winter") { + it("is coming") { + // ... + } + } + } + @endcode + + See DSL.swift for more information on what syntax is available. + */ +- (void)spec; + +/** + Returns the currently executing spec. Use in specs that require XCTestCase + methds, e.g. expectationWithDescription. +*/ +@property (class, nonatomic, readonly) QuickSpec *current; + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m new file mode 100644 index 0000000..4d5d37b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m @@ -0,0 +1,149 @@ +#import "QuickSpec.h" +#import "QuickConfiguration.h" +#import "World.h" +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +static QuickSpec *currentSpec = nil; + +@interface QuickSpec () +@property (nonatomic, strong) Example *example; +@end + +@implementation QuickSpec + +#pragma mark - XCTestCase Overrides + +/** + The runtime sends initialize to each class in a program just before the class, or any class + that inherits from it, is sent its first message from within the program. QuickSpec hooks into + this event to compile the example groups for this spec subclass. + + If an exception occurs when compiling the examples, report it to the user. Chances are they + included an expectation outside of a "it", "describe", or "context" block. + */ ++ (void)initialize { + [QuickConfiguration initialize]; + + World *world = [World sharedWorld]; + [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ + QuickSpec *spec = [self new]; + + @try { + [spec spec]; + } + @catch (NSException *exception) { + [NSException raise:NSInternalInconsistencyException + format:@"An exception occurred when building Quick's example groups.\n" + @"Some possible reasons this might happen include:\n\n" + @"- An 'expect(...).to' expectation was evaluated outside of " + @"an 'it', 'context', or 'describe' block\n" + @"- 'sharedExamples' was called twice with the same name\n" + @"- 'itBehavesLike' was called with a name that is not registered as a shared example\n\n" + @"Here's the original exception: '%@', reason: '%@', userInfo: '%@'", + exception.name, exception.reason, exception.userInfo]; + } + [self testInvocations]; + }]; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; + + NSMutableSet *selectorNames = [NSMutableSet set]; + + for (Example *example in examples) { + SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; + + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + +#pragma mark - Public Interface + +- (void)spec { } + ++ (QuickSpec*) current { + return currentSpec; +} + +#pragma mark - Internal Methods + +/** + QuickSpec uses this method to dynamically define a new instance method for the + given example. The instance method runs the example, catching any exceptions. + The exceptions are then reported as test failures. + + In order to report the correct file and line number, examples must raise exceptions + containing following keys in their userInfo: + + - "SenTestFilenameKey": A String representing the file name + - "SenTestLineNumberKey": An Int representing the line number + + These keys used to be used by SenTestingKit, and are still used by some testing tools + in the wild. See: https://github.com/Quick/Quick/pull/41 + + @return The selector of the newly defined instance method. + */ ++ (SEL)addInstanceMethodForExample:(Example *)example classSelectorNames:(NSMutableSet *)selectorNames { + IMP implementation = imp_implementationWithBlock(^(QuickSpec *self){ + self.example = example; + currentSpec = self; + [example run]; + }); + + const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(void), @encode(id), @encode(SEL)] UTF8String]; + + NSString *originalName = example.name.qck_c99ExtendedIdentifier; + NSString *selectorName = originalName; + NSUInteger i = 2; + + while ([selectorNames containsObject:selectorName]) { + selectorName = [NSString stringWithFormat:@"%@_%tu", originalName, i++]; + } + + [selectorNames addObject:selectorName]; + + SEL selector = NSSelectorFromString(selectorName); + class_addMethod(self, selector, implementation, types); + + return selector; +} + +/** + This method is used to record failures, whether they represent example + expectations that were not met, or exceptions raised during test setup + and teardown. By default, the failure will be reported as an + XCTest failure, and the example will be highlighted in Xcode. + */ +- (void)recordFailureWithDescription:(NSString *)description + inFile:(NSString *)filePath + atLine:(NSUInteger)lineNumber + expected:(BOOL)expected { + if (self.example.isSharedExample) { + filePath = self.example.callsite.file; + lineNumber = self.example.callsite.line; + } + [currentSpec.testRun recordFailureWithDescription:description + inFile:filePath + atLine:lineNumber + expected:expected]; +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h new file mode 100644 index 0000000..8cfed06 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h @@ -0,0 +1,22 @@ +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +@class ExampleGroup; +@class ExampleMetadata; + +SWIFT_CLASS("_TtC5Quick5World") +@interface World + +@property (nonatomic) ExampleGroup * __nullable currentExampleGroup; +@property (nonatomic) ExampleMetadata * __nullable currentExampleMetadata; +@property (nonatomic) BOOL isRunningAdditionalSuites; ++ (World * __nonnull)sharedWorld; +- (void)configure:(void (^ __nonnull)(Configuration * __nonnull))closure; +- (void)finalizeConfiguration; +- (ExampleGroup * __nonnull)rootExampleGroupForSpecClass:(Class __nonnull)cls; +- (NSArray * __nonnull)examplesForSpecClass:(Class __nonnull)specClass; +- (void)performWithCurrentExampleGroup:(ExampleGroup * __nonnull)group closure:(void (^ __nonnull)(void))closure; +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m new file mode 100644 index 0000000..e39ed69 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m @@ -0,0 +1,44 @@ +#import +#import +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +@interface XCTestSuite (QuickTestSuiteBuilder) +@end + +@implementation XCTestSuite (QuickTestSuiteBuilder) + +/** + In order to ensure we can correctly build dynamic test suites, we need to + replace some of the default test suite constructors. + */ ++ (void)load { + Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:)); + Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:)); + method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName); +} + +/** + The `+testSuiteForTestCaseWithName:` method is called when a specific test case + class is run from the Xcode test navigator. If the built test suite is `nil`, + Xcode will not run any tests for that test case. + + Given if the following test case class is run from the Xcode test navigator: + + FooSpec + testFoo + testBar + + XCTest will invoke this once per test case, with test case names following this format: + + FooSpec/testFoo + FooSpec/testBar + */ ++ (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name { + return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name]; +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m new file mode 100644 index 0000000..10b6f7e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m @@ -0,0 +1,55 @@ +#import "QuickSpecBase.h" + +#pragma mark - _QuickSelectorWrapper + +@interface _QuickSelectorWrapper () +@property(nonatomic, assign) SEL selector; +@end + +@implementation _QuickSelectorWrapper + +- (instancetype)initWithSelector:(SEL)selector { + self = [super init]; + _selector = selector; + return self; +} + +@end + + +#pragma mark - _QuickSpecBase + +@implementation _QuickSpecBase + +- (instancetype)init { + self = [super initWithInvocation: nil]; + return self; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:wrappers.count]; + + for (_QuickSelectorWrapper *wrapper in wrappers) { + SEL selector = wrapper.selector; + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors { + return @[]; +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h new file mode 100644 index 0000000..8881ca0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h @@ -0,0 +1,11 @@ +#import +#import + +@interface _QuickSelectorWrapper : NSObject +- (instancetype)initWithSelector:(SEL)selector; +@end + +@interface _QuickSpecBase : XCTestCase ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors; +- (instancetype)init NS_DESIGNATED_INITIALIZER; +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/LinuxMain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/LinuxMain.swift new file mode 100644 index 0000000..2a67c4a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/LinuxMain.swift @@ -0,0 +1,45 @@ +import XCTest +import Quick + +@testable import QuickTests + +Quick.QCKMain([ + FunctionalTests_AfterEachSpec.self, + AfterSuiteTests.self, + FunctionalTests_BeforeEachSpec.self, + FunctionalTests_BeforeSuite_BeforeSuiteSpec.self, + FunctionalTests_BeforeSuite_Spec.self, + FunctionalTests_ItSpec.self, + FunctionalTests_PendingSpec.self, + FunctionalTests_SharedExamples_BeforeEachSpec.self, + FunctionalTests_SharedExamples_Spec.self, + FunctionalTests_SharedExamples_ContextSpec.self, + Configuration_AfterEachSpec.self, + Configuration_BeforeEachSpec.self, + FunctionalTests_CrossReferencingSpecA.self, + FunctionalTests_CrossReferencingSpecB.self, + _FunctionalTests_FocusedSpec_Focused.self, + _FunctionalTests_FocusedSpec_Unfocused.self +], +configurations: [ + FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples.self, + FunctionalTests_SharedExamplesTests_SharedExamples.self, + FunctionalTests_Configuration_AfterEach.self, + FunctionalTests_Configuration_BeforeEach.self, + FunctionalTests_FocusedSpec_SharedExamplesConfiguration.self +], +testCases: [ + testCase(AfterEachTests.allTests), + testCase(BeforeEachTests.allTests), + testCase(BeforeSuiteTests.allTests), + // testCase(DescribeTests.allTests), + testCase(ItTests.allTests), + testCase(PendingTests.allTests), + testCase(SharedExamples_BeforeEachTests.allTests), + testCase(SharedExamplesTests.allTests), + testCase(Configuration_AfterEachTests.allTests), + testCase(Configuration_BeforeEachTests.allTests), + testCase(FocusedTests.allTests), + testCase(FunctionalTests_CrossReferencingSpecA.allTests), + testCase(FunctionalTests_CrossReferencingSpecB.allTests) +]) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m new file mode 100644 index 0000000..cd3522d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m @@ -0,0 +1,32 @@ +@import XCTest; +@import Quick; +@import Nimble; + +static BOOL afterSuiteFirstTestExecuted = NO; +static BOOL afterSuiteTestsWasExecuted = NO; + +@interface AfterSuiteTests_ObjC : QuickSpec + +@end + +@implementation AfterSuiteTests_ObjC + +- (void)spec { + it(@"is executed before afterSuite", ^{ + expect(@(afterSuiteTestsWasExecuted)).to(beFalsy()); + }); + + afterSuite(^{ + afterSuiteTestsWasExecuted = YES; + }); +} + ++ (void)tearDown { + if (afterSuiteFirstTestExecuted) { + assert(afterSuiteTestsWasExecuted); + } else { + afterSuiteFirstTestExecuted = true; + } +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift new file mode 100644 index 0000000..ea4fc3e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift @@ -0,0 +1,26 @@ +import XCTest +import Quick +import Nimble + +var afterSuiteFirstTestExecuted = false +var afterSuiteTestsWasExecuted = false + +class AfterSuiteTests: QuickSpec { + override func spec() { + afterSuite { + afterSuiteTestsWasExecuted = true + } + + it("is executed before afterSuite") { + expect(afterSuiteTestsWasExecuted).to(beFalsy()) + } + } + + override class func tearDown() { + if afterSuiteFirstTestExecuted { + assert(afterSuiteTestsWasExecuted, "afterSuiteTestsWasExecuted needs to be true") + } else { + afterSuiteFirstTestExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m new file mode 100644 index 0000000..5069f2b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m @@ -0,0 +1,56 @@ +@import Quick; +@import Nimble; +@import XCTest; + +#import "QCKSpecRunner.h" + +QuickConfigurationBegin(FunctionalTests_SharedExamplesConfiguration_ObjC) + ++ (void)configure:(Configuration *)configuration { + sharedExamples(@"two passing shared examples (Objective-C)", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"has an example that passes (4)", ^{}); + it(@"has another example that passes (5)", ^{}); + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(FunctionalTests_FocusedSpec_Focused_ObjC) + +it(@"has an unfocused example that fails, but is never run", ^{ XCTFail(); }); +fit(@"has a focused example that passes (1)", ^{}); + +fdescribe(@"a focused example group", ^{ + it(@"has an example that is not focused, but will be run, and passes (2)", ^{}); + fit(@"has a focused example that passes (3)", ^{}); +}); + +fitBehavesLike(@"two passing shared examples (Objective-C)", ^NSDictionary *{ return @{}; }); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_FocusedSpec_Unfocused_ObjC) + +it(@"has an unfocused example thay fails, but is never run", ^{ XCTFail(); }); + +describe(@"an unfocused example group that is never run", ^{ + beforeEach(^{ [NSException raise:NSInternalInconsistencyException format:@""]; }); + it(@"has an example that fails, but is never run", ^{ XCTFail(); }); +}); + +QuickSpecEnd + +@interface FocusedTests_ObjC: XCTestCase +@end + +@implementation FocusedTests_ObjC + +- (void)testOnlyFocusedExamplesAreExecuted { + XCTestRun *result = qck_runSpecs(@[ + [FunctionalTests_FocusedSpec_Focused_ObjC class], + [FunctionalTests_FocusedSpec_Unfocused_ObjC class] + ]); + XCTAssertEqual(result.executionCount, 5); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift new file mode 100644 index 0000000..132b748 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift @@ -0,0 +1,68 @@ +import Quick +import Nimble +import XCTest + +class FunctionalTests_FocusedSpec_SharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("two passing shared examples") { + it("has an example that passes (4)") {} + it("has another example that passes (5)") {} + } + } +} + +class FunctionalTests_FocusedSpec_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("pass once") { expect(true).to(beTruthy()) } + it("pass twice") { expect(true).to(beTruthy()) } + it("pass three times") { expect(true).to(beTruthy()) } + } +} + +// The following `QuickSpec`s will be run in a same test suite with other specs +// on SwiftPM. We must avoid that the focused flags below affect other specs, so +// the examples of the two specs must be gathered lastly. That is the reason why +// the two specs have underscore prefix (and are listed at the bottom of `QCKMain`s +// `specs` array). + +class _FunctionalTests_FocusedSpec_Focused: QuickSpec { + override func spec() { + it("has an unfocused example that fails, but is never run") { fail() } + fit("has a focused example that passes (1)") {} + + fdescribe("a focused example group") { + it("has an example that is not focused, but will be run, and passes (2)") {} + fit("has a focused example that passes (3)") {} + } + + fitBehavesLike("two passing shared examples") + fitBehavesLike(FunctionalTests_FocusedSpec_Behavior.self) { () -> Void in } + } +} + +class _FunctionalTests_FocusedSpec_Unfocused: QuickSpec { + override func spec() { + it("has an unfocused example that fails, but is never run") { fail() } + + describe("an unfocused example group that is never run") { + beforeEach { assert(false) } + it("has an example that fails, but is never run") { fail() } + } + } +} + +final class FocusedTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (FocusedTests) -> () throws -> Void)] { + return [ + ("testOnlyFocusedExamplesAreExecuted", testOnlyFocusedExamplesAreExecuted) + ] + } + + func testOnlyFocusedExamplesAreExecuted() { + let result = qck_runSpecs([ + _FunctionalTests_FocusedSpec_Focused.self, + _FunctionalTests_FocusedSpec_Unfocused.self + ]) + XCTAssertEqual(result?.executionCount, 8) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift new file mode 100644 index 0000000..66dec1b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift @@ -0,0 +1,30 @@ +@testable import Quick +import Nimble + +@discardableResult +public func qck_runSpec(_ specClass: QuickSpec.Type) -> TestRun? { + return qck_runSpecs([specClass]) +} + +@discardableResult +public func qck_runSpecs(_ specClasses: [QuickSpec.Type]) -> TestRun? { + Quick.World.sharedWorld.isRunningAdditionalSuites = true + + var executionCount: UInt = 0 + var hadUnexpectedFailure = false + + let fails = gatherFailingExpectations(silently: true) { + for specClass in specClasses { + for (_, test) in specClass.allTests { + do { + try test(specClass.init())() + } catch { + hadUnexpectedFailure = true + } + executionCount += 1 + } + } + } + + return TestRun(executionCount: executionCount, hasSucceeded: fails.isEmpty && !hadUnexpectedFailure) +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift new file mode 100644 index 0000000..3ef0d6c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift @@ -0,0 +1,9 @@ +public struct TestRun { + public var executionCount: UInt + public var hasSucceeded: Bool + + public init(executionCount: UInt, hasSucceeded: Bool) { + self.executionCount = executionCount + self.hasSucceeded = hasSucceeded + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..304eb30 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +public extension XCTestCaseProvider where Self: XCTestCaseProviderStatic { + var allTestNames: [String] { + return type(of: self).allTests.map { name, _ in + return name + } + } +} + +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + + extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } + } + + extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } + } + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift new file mode 100644 index 0000000..7e004d1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift @@ -0,0 +1,20 @@ +import Foundation +import Quick +import Nimble + +class FunctionalTests_BehaviorTests_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> String) { + it("passed the correct parameters via the context") { + let callsite = aContext() + expect(callsite).to(equal("BehaviorSpec")) + } + } +} + +class FunctionalTests_BehaviorTests_Behavior2: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("passes once") { expect(true).to(beTruthy()) } + it("passes twice") { expect(true).to(beTruthy()) } + it("passes three times") { expect(true).to(beTruthy()) } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift new file mode 100644 index 0000000..e5eed68 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift @@ -0,0 +1,20 @@ +import Foundation +import Quick +import Nimble + +class FunctionalTests_SharedExamplesTests_SharedExamples: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("a group of three shared examples") { + it("passes once") { expect(true).to(beTruthy()) } + it("passes twice") { expect(true).to(beTruthy()) } + it("passes three times") { expect(true).to(beTruthy()) } + } + + sharedExamples("shared examples that take a context") { (sharedExampleContext: @escaping SharedExampleContext) in + it("is passed the correct parameters via the context") { + let callsite = sharedExampleContext()["callsite"] as? String + expect(callsite).to(equal("SharedExamplesSpec")) + } + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift new file mode 100644 index 0000000..45f6203 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift @@ -0,0 +1,92 @@ +import XCTest +import Quick +import Nimble + +private enum AfterEachType { + case outerOne + case outerTwo + case outerThree + case innerOne + case innerTwo + case noExamples +} + +private var afterEachOrder = [AfterEachType]() + +class FunctionalTests_AfterEachSpec: QuickSpec { + override func spec() { + describe("afterEach ordering") { + afterEach { afterEachOrder.append(.outerOne) } + afterEach { afterEachOrder.append(.outerTwo) } + afterEach { afterEachOrder.append(.outerThree) } + + it("executes the outer afterEach closures once, but not before this closure [1]") { + // No examples have been run, so no afterEach will have been run either. + // The list should be empty. + expect(afterEachOrder).to(beEmpty()) + } + + it("executes the outer afterEach closures a second time, but not before this closure [2]") { + // The afterEach for the previous example should have been run. + // The list should contain the afterEach for that example, executed from top to bottom. + expect(afterEachOrder).to(equal([.outerOne, .outerTwo, .outerThree])) + } + + context("when there are nested afterEach") { + afterEach { afterEachOrder.append(.innerOne) } + afterEach { afterEachOrder.append(.innerTwo) } + + it("executes the outer and inner afterEach closures, but not before this closure [3]") { + // The afterEach for the previous two examples should have been run. + // The list should contain the afterEach for those example, executed from top to bottom. + expect(afterEachOrder).to(equal([ + .outerOne, .outerTwo, .outerThree, + .outerOne, .outerTwo, .outerThree + ])) + } + } + + context("when there are nested afterEach without examples") { + afterEach { afterEachOrder.append(.noExamples) } + } + } +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + describe("error handling when misusing ordering") { + it("should throw an exception when including afterEach in it block") { + expect { + afterEach { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'afterEach' cannot be used inside 'it', 'afterEach' may only be used inside 'context' or 'describe'. ")) + }) + } + } +#endif + } +} + +final class AfterEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AfterEachTests) -> () throws -> Void)] { + return [ + ("testAfterEachIsExecutedInTheCorrectOrder", testAfterEachIsExecutedInTheCorrectOrder) + ] + } + + func testAfterEachIsExecutedInTheCorrectOrder() { + afterEachOrder = [] + + qck_runSpec(FunctionalTests_AfterEachSpec.self) + let expectedOrder: [AfterEachType] = [ + // [1] The outer afterEach closures are executed from top to bottom. + .outerOne, .outerTwo, .outerThree, + // [2] The outer afterEach closures are executed from top to bottom. + .outerOne, .outerTwo, .outerThree, + // [3] The inner afterEach closures are executed from top to bottom, + // then the outer afterEach closures are executed from top to bottom. + .innerOne, .innerTwo, .outerOne, .outerTwo, .outerThree + ] + XCTAssertEqual(afterEachOrder, expectedOrder) + + afterEachOrder = [] + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift new file mode 100644 index 0000000..6709051 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift @@ -0,0 +1,75 @@ +import XCTest +import Quick +import Nimble + +private enum BeforeEachType { + case outerOne + case outerTwo + case innerOne + case innerTwo + case innerThree + case noExamples +} + +private var beforeEachOrder = [BeforeEachType]() + +class FunctionalTests_BeforeEachSpec: QuickSpec { + override func spec() { + + describe("beforeEach ordering") { + beforeEach { beforeEachOrder.append(.outerOne) } + beforeEach { beforeEachOrder.append(.outerTwo) } + + it("executes the outer beforeEach closures once [1]") {} + it("executes the outer beforeEach closures a second time [2]") {} + + context("when there are nested beforeEach") { + beforeEach { beforeEachOrder.append(.innerOne) } + beforeEach { beforeEachOrder.append(.innerTwo) } + beforeEach { beforeEachOrder.append(.innerThree) } + + it("executes the outer and inner beforeEach closures [3]") {} + } + + context("when there are nested beforeEach without examples") { + beforeEach { beforeEachOrder.append(.noExamples) } + } + } +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + describe("error handling when misusing ordering") { + it("should throw an exception when including beforeEach in it block") { + expect { + beforeEach { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'beforeEach' cannot be used inside 'it', 'beforeEach' may only be used inside 'context' or 'describe'. ")) + }) + } + } +#endif + } +} + +final class BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeforeEachTests) -> () throws -> Void)] { + return [ + ("testBeforeEachIsExecutedInTheCorrectOrder", testBeforeEachIsExecutedInTheCorrectOrder) + ] + } + + func testBeforeEachIsExecutedInTheCorrectOrder() { + beforeEachOrder = [] + + qck_runSpec(FunctionalTests_BeforeEachSpec.self) + let expectedOrder: [BeforeEachType] = [ + // [1] The outer beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, + // [2] The outer beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, + // [3] The outer beforeEach closures are executed from top to bottom, + // then the inner beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, .innerOne, .innerTwo, .innerThree + ] + XCTAssertEqual(beforeEachOrder, expectedOrder) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift new file mode 100644 index 0000000..df39126 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift @@ -0,0 +1,39 @@ +import XCTest +import Quick +import Nimble + +var beforeSuiteWasExecuted = false + +class FunctionalTests_BeforeSuite_BeforeSuiteSpec: QuickSpec { + override func spec() { + beforeSuite { + beforeSuiteWasExecuted = true + } + } +} + +class FunctionalTests_BeforeSuite_Spec: QuickSpec { + override func spec() { + it("is executed after beforeSuite") { + expect(beforeSuiteWasExecuted).to(beTruthy()) + } + } +} + +final class BeforeSuiteTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeforeSuiteTests) -> () throws -> Void)] { + return [ + ("testBeforeSuiteIsExecutedBeforeAnyExamples", testBeforeSuiteIsExecutedBeforeAnyExamples) + ] + } + + func testBeforeSuiteIsExecutedBeforeAnyExamples() { + // Execute the spec with an assertion before the one with a beforeSuite + let result = qck_runSpecs([ + FunctionalTests_BeforeSuite_Spec.self, + FunctionalTests_BeforeSuite_BeforeSuiteSpec.self + ]) + + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift new file mode 100644 index 0000000..21dadfe --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift @@ -0,0 +1,59 @@ +import Foundation +import Quick +import Nimble +import XCTest + +class FunctionalTests_BehaviorTests_Spec: QuickSpec { + override func spec() { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior2.self) { () -> Void in } + } +} + +class FunctionalTests_BehaviorTests_ContextSpec: QuickSpec { + override func spec() { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior.self) { + "BehaviorSpec" + } + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class FunctionalTests_BehaviorTests_ErrorSpec: QuickSpec { + override func spec() { + describe("error handling when misusing ordering") { + it("should throw an exception when including itBehavesLike in it block") { + expect { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior2.self) { () } + } + .to(raiseException {(exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'itBehavesLike' cannot be used inside 'it', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif + +final class BehaviorTests: XCTestCase, XCTestCaseProvider { + + static var allTests: [(String, (BehaviorTests) -> () throws -> Void)] { + return [ + ("testBehaviorPassContextToExamples", + testBehaviorPassContextToExamples), + ("testBehaviorExecutesThreeExamples", + testBehaviorExecutesThreeExamples) + ] + } + + func testBehaviorExecutesThreeExamples() { + let result = qck_runSpec(FunctionalTests_BehaviorTests_Spec.self) + XCTAssert(result!.hasSucceeded) + XCTAssertEqual(result!.executionCount, 3) + } + + func testBehaviorPassContextToExamples() { + let result = qck_runSpec(FunctionalTests_BehaviorTests_ContextSpec.self) + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift new file mode 100644 index 0000000..4f99689 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift @@ -0,0 +1,30 @@ +#if !SWIFT_PACKAGE + +import XCTest +@testable import Quick +import Nimble + +class BundleModuleNameSpecs: QuickSpec { + override func spec() { + describe("Bundle module name") { + it("should repalce invalid characters with underscores") { + let bundle = Bundle.currentTestBundle + let moduleName = bundle?.moduleName + expect(moduleName?.contains("Quick_")).to(beTrue()) + } + + it("should be the correct module name to be able to retreive classes") { + guard let bundle = Bundle.currentTestBundle else { + XCTFail("test bundle not found") + return + } + + let moduleName = bundle.moduleName + let className: AnyClass? = NSClassFromString("\(moduleName).BundleModuleNameSpecs") + expect(className).to(be(BundleModuleNameSpecs.self)) + } + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift new file mode 100644 index 0000000..c3f6717 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift @@ -0,0 +1,11 @@ +import Quick + +public var FunctionalTests_Configuration_AfterEachWasExecuted = false + +class FunctionalTests_Configuration_AfterEach: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.afterEach { + FunctionalTests_Configuration_AfterEachWasExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift new file mode 100644 index 0000000..d7c2105 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift @@ -0,0 +1,31 @@ +import XCTest +import Quick +import Nimble + +class Configuration_AfterEachSpec: QuickSpec { + override func spec() { + beforeEach { + FunctionalTests_Configuration_AfterEachWasExecuted = false + } + it("is executed before the configuration afterEach") { + expect(FunctionalTests_Configuration_AfterEachWasExecuted).to(beFalsy()) + } + } +} + +final class Configuration_AfterEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (Configuration_AfterEachTests) -> () throws -> Void)] { + return [ + ("testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted", testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted) + ] + } + + func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { + FunctionalTests_Configuration_AfterEachWasExecuted = false + + qck_runSpec(Configuration_BeforeEachSpec.self) + XCTAssert(FunctionalTests_Configuration_AfterEachWasExecuted) + + FunctionalTests_Configuration_AfterEachWasExecuted = false + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift new file mode 100644 index 0000000..228ab98 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift @@ -0,0 +1,11 @@ +import Quick + +public var FunctionalTests_Configuration_BeforeEachWasExecuted = false + +class FunctionalTests_Configuration_BeforeEach: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { + FunctionalTests_Configuration_BeforeEachWasExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift new file mode 100644 index 0000000..ddf1509 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift @@ -0,0 +1,28 @@ +import XCTest +import Quick +import Nimble + +class Configuration_BeforeEachSpec: QuickSpec { + override func spec() { + it("is executed after the configuration beforeEach") { + expect(FunctionalTests_Configuration_BeforeEachWasExecuted).to(beTruthy()) + } + } +} + +final class Configuration_BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (Configuration_BeforeEachTests) -> () throws -> Void)] { + return [ + ("testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted", testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted) + ] + } + + func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { + FunctionalTests_Configuration_BeforeEachWasExecuted = false + + qck_runSpec(Configuration_BeforeEachSpec.self) + XCTAssert(FunctionalTests_Configuration_BeforeEachWasExecuted) + + FunctionalTests_Configuration_BeforeEachWasExecuted = false + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift new file mode 100644 index 0000000..ab619be --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift @@ -0,0 +1,20 @@ +import XCTest +import Quick +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class QuickContextTests: QuickSpec { + override func spec() { + describe("Context") { + it("should throw an exception if used in an it block") { + expect { + context("A nested context that should throw") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'context' cannot be used inside 'it', 'context' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift new file mode 100644 index 0000000..5fc3d7b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift @@ -0,0 +1,19 @@ +import Quick +import Nimble + +// This is a functional test ensuring that no crash occurs when a spec class +// references another spec class during its spec setup. + +class FunctionalTests_CrossReferencingSpecA: QuickSpec { + override func spec() { + _ = FunctionalTests_CrossReferencingSpecB() + it("does not crash") {} + } +} + +class FunctionalTests_CrossReferencingSpecB: QuickSpec { + override func spec() { + _ = FunctionalTests_CrossReferencingSpecA() + it("does not crash") {} + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift new file mode 100644 index 0000000..05b37f7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift @@ -0,0 +1,25 @@ +import Quick +import Nimble + +#if !SWIFT_PACKAGE + +class CurrentSpecTests: QuickSpec { + override func spec() { + it("returns the currently executing spec") { + expect(QuickSpec.current?.name).to(match("currently_executing_spec")) + } + + let currentSpecDuringSpecSetup = QuickSpec.current + it("returns nil when no spec is executing") { + expect(currentSpecDuringSpecSetup).to(beNil()) + } + + it("supports XCTest expectations") { + let expectation = QuickSpec.current.expectation(description: "great expectation") + DispatchQueue.main.async(execute: expectation.fulfill) + QuickSpec.current.waitForExpectations(timeout: 1) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift new file mode 100644 index 0000000..6c4ac07 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift @@ -0,0 +1,34 @@ +import XCTest +import Nimble +import Quick + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class DescribeTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (DescribeTests) -> () throws -> Void)] { + return [ + ("testDescribeThrowsIfUsedOutsideOfQuickSpec", testDescribeThrowsIfUsedOutsideOfQuickSpec) + ] + } + + func testDescribeThrowsIfUsedOutsideOfQuickSpec() { + expect { describe("this should throw an exception", {}) }.to(raiseException()) + } +} + +class QuickDescribeTests: QuickSpec { + override func spec() { + describe("Describe") { + it("should throw an exception if used in an it block") { + expect { + describe("A nested describe that should throw") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'describe' cannot be used inside 'it', 'describe' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} + +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift new file mode 100644 index 0000000..106cf30 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift @@ -0,0 +1,127 @@ +import XCTest +@testable import Quick +import Nimble + +class FunctionalTests_ItSpec: QuickSpec { + override func spec() { + var exampleMetadata: ExampleMetadata? + beforeEach { metadata in exampleMetadata = metadata } + + it("") { + expect(exampleMetadata!.example.name).to(equal("")) + } + + it("has a description with セレクター名に使えない文字が入っている 👊💥") { + let name = "has a description with セレクター名に使えない文字が入っている 👊💥" + expect(exampleMetadata!.example.name).to(equal(name)) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + + describe("when an example has a unique name") { + it("has a unique name") {} + + it("doesn't add multiple selectors for it") { + let allSelectors = [String]( + FunctionalTests_ItSpec.allSelectors() + .filter { $0.hasPrefix("when_an_example_has_a_unique_name__") }) + .sorted(by: <) + + expect(allSelectors) == [ + "when_an_example_has_a_unique_name__doesn_t_add_multiple_selectors_for_it", + "when_an_example_has_a_unique_name__has_a_unique_name" + ] + } + } + + describe("when two examples have the exact name") { + it("has exactly the same name") {} + it("has exactly the same name") {} + + it("makes a unique name for each of the above") { + let allSelectors = [String]( + FunctionalTests_ItSpec.allSelectors() + .filter { $0.hasPrefix("when_two_examples_have_the_exact_name__") }) + .sorted(by: <) + + expect(allSelectors) == [ + "when_two_examples_have_the_exact_name__has_exactly_the_same_name", + "when_two_examples_have_the_exact_name__has_exactly_the_same_name_2", + "when_two_examples_have_the_exact_name__makes_a_unique_name_for_each_of_the_above" + ] + } + + } + + describe("error handling when misusing ordering") { + it("an it") { + expect { + it("will throw an error when it is nested in another it") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ")) + }) + } + + describe("behavior with an 'it' inside a 'beforeEach'") { + var exception: NSException? + + beforeEach { + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + it("a rogue 'it' inside a 'beforeEach'") { } + return + } + } + + it("should have thrown an exception with the correct error message") { + expect(exception).toNot(beNil()) + expect(exception!.reason).to(equal("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ")) + } + } + + describe("behavior with an 'it' inside an 'afterEach'") { + var exception: NSException? + + afterEach { + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + expect(exception).toNot(beNil()) + expect(exception!.reason).to(equal("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ")) + }), finally: nil) + + capture.tryBlock { + it("a rogue 'it' inside an 'afterEach'") { } + return + } + } + + it("should throw an exception with the correct message after this 'it' block executes") { } + } + } +#endif + } +} + +final class ItTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ItTests) -> () throws -> Void)] { + return [ + ("testAllExamplesAreExecuted", testAllExamplesAreExecuted) + ] + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 10) + } +#else + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 2) + } +#endif +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m new file mode 100644 index 0000000..4216a86 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m @@ -0,0 +1,81 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +typedef NS_ENUM(NSUInteger, AfterEachType) { + OuterOne, + OuterTwo, + OuterThree, + InnerOne, + InnerTwo, + NoExamples, +}; + +static NSMutableArray *afterEachOrder; + +QuickSpecBegin(FunctionalTests_AfterEachSpec_ObjC) + +afterEach(^{ [afterEachOrder addObject:@(OuterOne)]; }); +afterEach(^{ [afterEachOrder addObject:@(OuterTwo)]; }); +afterEach(^{ [afterEachOrder addObject:@(OuterThree)]; }); + +it(@"executes the outer afterEach closures once, but not before this closure [1]", ^{ + expect(afterEachOrder).to(equal(@[])); +}); + +it(@"executes the outer afterEach closures a second time, but not before this closure [2]", ^{ + expect(afterEachOrder).to(equal(@[@(OuterOne), @(OuterTwo), @(OuterThree)])); +}); + +context(@"when there are nested afterEach", ^{ + afterEach(^{ [afterEachOrder addObject:@(InnerOne)]; }); + afterEach(^{ [afterEachOrder addObject:@(InnerTwo)]; }); + + it(@"executes the outer and inner afterEach closures, but not before this closure [3]", ^{ + // The afterEach for the previous two examples should have been run. + // The list should contain the afterEach for those example, executed from top to bottom. + expect(afterEachOrder).to(equal(@[ + @(OuterOne), @(OuterTwo), @(OuterThree), + @(OuterOne), @(OuterTwo), @(OuterThree), + ])); + }); +}); + +context(@"when there are nested afterEach without examples", ^{ + afterEach(^{ [afterEachOrder addObject:@(NoExamples)]; }); +}); + +QuickSpecEnd + +@interface AfterEachTests_ObjC : XCTestCase; @end + +@implementation AfterEachTests_ObjC + +- (void)setUp { + [super setUp]; + afterEachOrder = [NSMutableArray array]; +} + +- (void)tearDown { + afterEachOrder = [NSMutableArray array]; + [super tearDown]; +} + +- (void)testAfterEachIsExecutedInTheCorrectOrder { + qck_runSpec([FunctionalTests_AfterEachSpec_ObjC class]); + NSArray *expectedOrder = @[ + // [1] The outer afterEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(OuterThree), + // [2] The outer afterEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(OuterThree), + // [3] The outer afterEach closures are executed from top to bottom, + // then the outer afterEach closures are executed from top to bottom. + @(InnerOne), @(InnerTwo), @(OuterOne), @(OuterTwo), @(OuterThree), + ]; + + XCTAssertEqualObjects(afterEachOrder, expectedOrder); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m new file mode 100644 index 0000000..c7a5897 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m @@ -0,0 +1,68 @@ +@import XCTest; +@import Quick; + +#import "QCKSpecRunner.h" + +typedef NS_ENUM(NSUInteger, BeforeEachType) { + OuterOne, + OuterTwo, + InnerOne, + InnerTwo, + InnerThree, + NoExamples, +}; + +static NSMutableArray *beforeEachOrder; + +QuickSpecBegin(FunctionalTests_BeforeEachSpec_ObjC) + +beforeEach(^{ [beforeEachOrder addObject:@(OuterOne)]; }); +beforeEach(^{ [beforeEachOrder addObject:@(OuterTwo)]; }); + +it(@"executes the outer beforeEach closures once [1]", ^{}); +it(@"executes the outer beforeEach closures a second time [2]", ^{}); + +context(@"when there are nested beforeEach", ^{ + beforeEach(^{ [beforeEachOrder addObject:@(InnerOne)]; }); + beforeEach(^{ [beforeEachOrder addObject:@(InnerTwo)]; }); + beforeEach(^{ [beforeEachOrder addObject:@(InnerThree)]; }); + + it(@"executes the outer and inner beforeEach closures [3]", ^{}); +}); + +context(@"when there are nested beforeEach without examples", ^{ + beforeEach(^{ [beforeEachOrder addObject:@(NoExamples)]; }); +}); + +QuickSpecEnd + +@interface BeforeEachTests_ObjC : XCTestCase; @end + +@implementation BeforeEachTests_ObjC + +- (void)setUp { + beforeEachOrder = [NSMutableArray array]; + [super setUp]; +} + +- (void)tearDown { + beforeEachOrder = [NSMutableArray array]; + [super tearDown]; +} + +- (void)testBeforeEachIsExecutedInTheCorrectOrder { + qck_runSpec([FunctionalTests_BeforeEachSpec_ObjC class]); + NSArray *expectedOrder = @[ + // [1] The outer beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), + // [2] The outer beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), + // [3] The outer beforeEach closures are executed from top to bottom, + // then the inner beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(InnerOne), @(InnerTwo), @(InnerThree), + ]; + + XCTAssertEqualObjects(beforeEachOrder, expectedOrder); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m new file mode 100644 index 0000000..ce7efc9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m @@ -0,0 +1,39 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static BOOL beforeSuiteWasExecuted = NO; + +QuickSpecBegin(FunctionalTests_BeforeSuite_BeforeSuiteSpec_ObjC) + +beforeSuite(^{ + beforeSuiteWasExecuted = YES; +}); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_BeforeSuite_Spec_ObjC) + +it(@"is executed after beforeSuite", ^{ + expect(@(beforeSuiteWasExecuted)).to(beTruthy()); +}); + +QuickSpecEnd + +@interface BeforeSuiteTests_ObjC : XCTestCase; @end + +@implementation BeforeSuiteTests_ObjC + +- (void)testBeforeSuiteIsExecutedBeforeAnyExamples { + // Execute the spec with an assertion before the one with a beforeSuite + NSArray *specs = @[ + [FunctionalTests_BeforeSuite_Spec_ObjC class], + [FunctionalTests_BeforeSuite_BeforeSuiteSpec_ObjC class] + ]; + XCTestRun *result = qck_runSpecs(specs); + XCTAssert(result.hasSucceeded); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m new file mode 100644 index 0000000..dc786e8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m @@ -0,0 +1,61 @@ +@import XCTest; + +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static BOOL isRunningFunctionalTests = NO; + +#pragma mark - Spec + +QuickSpecBegin(FunctionalTests_FailureSpec_ObjC) + +describe(@"a group of failing examples", ^{ + it(@"passes", ^{ + expect(@YES).to(beTruthy()); + }); + + it(@"fails (but only when running the functional tests)", ^{ + expect(@(isRunningFunctionalTests)).to(beFalsy()); + }); + + it(@"fails again (but only when running the functional tests)", ^{ + expect(@(isRunningFunctionalTests)).to(beFalsy()); + }); +}); + +QuickSpecEnd + +#pragma mark - Tests + +@interface FailureTests_ObjC : XCTestCase; @end + +@implementation FailureTests_ObjC + +- (void)setUp { + [super setUp]; + isRunningFunctionalTests = YES; +} + +- (void)tearDown { + isRunningFunctionalTests = NO; + [super tearDown]; +} + +- (void)testFailureSpecHasSucceededIsFalse { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertFalse(result.hasSucceeded); +} + +- (void)testFailureSpecExecutedAllExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testFailureSpecFailureCountIsEqualToTheNumberOfFailingExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertEqual(result.failureCount, 2); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m new file mode 100644 index 0000000..70fb245 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m @@ -0,0 +1,55 @@ +@import XCTest; +@import Quick; + +#import "QCKSpecRunner.h" + +static BOOL isRunningFunctionalTests = NO; + +QuickSpecBegin(FunctionalTests_FailureUsingXCTAssertSpec_ObjC) + +it(@"fails using an XCTAssert (but only when running the functional tests)", ^{ + XCTAssertFalse(isRunningFunctionalTests); +}); + +it(@"fails again using an XCTAssert (but only when running the functional tests)", ^{ + XCTAssertFalse(isRunningFunctionalTests); +}); + +it(@"succeeds using an XCTAssert", ^{ + XCTAssertTrue(YES); +}); + +QuickSpecEnd + +#pragma mark - Tests + +@interface FailureUsingXCTAssertTests_ObjC : XCTestCase; @end + +@implementation FailureUsingXCTAssertTests_ObjC + +- (void)setUp { + [super setUp]; + isRunningFunctionalTests = YES; +} + +- (void)tearDown { + isRunningFunctionalTests = NO; + [super tearDown]; +} + +- (void)testFailureUsingXCTAssertSpecHasSucceededIsFalse { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertFalse(result.hasSucceeded); +} + +- (void)testFailureUsingXCTAssertSpecExecutedAllExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testFailureUsingXCTAssertSpecFailureCountIsEqualToTheNumberOfFailingExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertEqual(result.totalFailureCount, 2); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m new file mode 100644 index 0000000..39e0b7d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m @@ -0,0 +1,42 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" +#import "QuickSpec+QuickSpec_MethodList.h" + +QuickSpecBegin(FunctionalTests_ItSpec_ObjC) + +__block ExampleMetadata *exampleMetadata = nil; +beforeEachWithMetadata(^(ExampleMetadata *metadata) { + exampleMetadata = metadata; +}); + +it(@" ", ^{ + expect(exampleMetadata.example.name).to(equal(@" ")); +}); + +it(@"has a description with セレクター名に使えない文字が入っている 👊💥", ^{ + NSString *name = @"has a description with セレクター名に使えない文字が入っている 👊💥"; + expect(exampleMetadata.example.name).to(equal(name)); +}); + +it(@"is a test with a unique name", ^{ + NSSet *allSelectors = [FunctionalTests_ItSpec_ObjC allSelectors]; + + expect(allSelectors).to(contain(@"is_a_test_with_a_unique_name")); + expect(allSelectors).toNot(contain(@"is_a_test_with_a_unique_name_2")); +}); + +QuickSpecEnd + +@interface ItTests_ObjC : XCTestCase; @end + +@implementation ItTests_ObjC + +- (void)testAllExamplesAreExecuted { + XCTestRun *result = qck_runSpec([FunctionalTests_ItSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m new file mode 100644 index 0000000..970175f --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m @@ -0,0 +1,60 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static NSUInteger oneExampleBeforeEachExecutedCount = 0; +static NSUInteger onlyPendingExamplesBeforeEachExecutedCount = 0; + +QuickSpecBegin(FunctionalTests_PendingSpec_ObjC) + +pending(@"an example that will not run", ^{ + expect(@YES).to(beFalsy()); +}); + +describe(@"a describe block containing only one enabled example", ^{ + beforeEach(^{ oneExampleBeforeEachExecutedCount += 1; }); + it(@"an example that will run", ^{}); + pending(@"an example that will not run", ^{}); +}); + +describe(@"a describe block containing only pending examples", ^{ + beforeEach(^{ onlyPendingExamplesBeforeEachExecutedCount += 1; }); + pending(@"an example that will not run", ^{}); +}); + +QuickSpecEnd + +@interface PendingTests_ObjC : XCTestCase; @end + +@implementation PendingTests_ObjC + +- (void)setUp { + [super setUp]; + oneExampleBeforeEachExecutedCount = 0; + onlyPendingExamplesBeforeEachExecutedCount = 0; +} + +- (void)tearDown { + oneExampleBeforeEachExecutedCount = 0; + onlyPendingExamplesBeforeEachExecutedCount = 0; + [super tearDown]; +} + +- (void)testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail { + XCTestRun *result = qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssert(result.hasSucceeded); +} + +- (void)testBeforeEachOnlyRunForEnabledExamples { + qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssertEqual(oneExampleBeforeEachExecutedCount, 1); +} + +- (void)testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples { + qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssertEqual(onlyPendingExamplesBeforeEachExecutedCount, 0); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m new file mode 100644 index 0000000..cdbf259 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m @@ -0,0 +1,59 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static NSUInteger specBeforeEachExecutedCount = 0; +static NSUInteger sharedExamplesBeforeEachExecutedCount = 0; + +QuickConfigurationBegin(FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples_ObjC) + ++ (void)configure:(Configuration *)configuration { + sharedExamples(@"a group of three shared examples with a beforeEach in Obj-C", + ^(QCKDSLSharedExampleContext context) { + beforeEach(^{ sharedExamplesBeforeEachExecutedCount += 1; }); + it(@"passes once", ^{}); + it(@"passes twice", ^{}); + it(@"passes three times", ^{}); + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_BeforeEachSpec_ObjC) + +beforeEach(^{ specBeforeEachExecutedCount += 1; }); +it(@"executes the spec beforeEach once", ^{}); +itBehavesLike(@"a group of three shared examples with a beforeEach in Obj-C", + ^NSDictionary*{ return @{}; }); + +QuickSpecEnd + +@interface SharedExamples_BeforeEachTests_ObjC : XCTestCase; @end + +@implementation SharedExamples_BeforeEachTests_ObjC + +- (void)setUp { + [super setUp]; + specBeforeEachExecutedCount = 0; + sharedExamplesBeforeEachExecutedCount = 0; +} + +- (void)tearDown { + specBeforeEachExecutedCount = 0; + sharedExamplesBeforeEachExecutedCount = 0; + [super tearDown]; +} + +- (void)testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample { + qck_runSpec([FunctionalTests_SharedExamples_BeforeEachSpec_ObjC class]); + XCTAssertEqual(specBeforeEachExecutedCount, 4); +} + +- (void)testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample { + qck_runSpec([FunctionalTests_SharedExamples_BeforeEachSpec_ObjC class]); + XCTAssertEqual(sharedExamplesBeforeEachExecutedCount, 3); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m new file mode 100644 index 0000000..7fcb8b1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m @@ -0,0 +1,65 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +QuickSpecBegin(FunctionalTests_SharedExamples_Spec_ObjC) + +itBehavesLike(@"a group of three shared examples", ^NSDictionary*{ return @{}; }); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_ContextSpec_ObjC) + +itBehavesLike(@"shared examples that take a context", ^NSDictionary *{ + return @{ @"callsite": @"SharedExamplesSpec" }; +}); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_SameContextSpec_ObjC) + +__block NSInteger counter = 0; + +afterEach(^{ + counter++; +}); + +sharedExamples(@"gets called with a different context from within the same spec file", ^(QCKDSLSharedExampleContext exampleContext) { + + it(@"tracks correctly", ^{ + NSString *payload = exampleContext()[@"payload"]; + BOOL expected = [payload isEqualToString:[NSString stringWithFormat:@"%ld", (long)counter]]; + expect(@(expected)).to(beTrue()); + }); + +}); + +itBehavesLike(@"gets called with a different context from within the same spec file", ^{ + return @{ @"payload" : @"0" }; +}); + +itBehavesLike(@"gets called with a different context from within the same spec file", ^{ + return @{ @"payload" : @"1" }; +}); + +QuickSpecEnd + + +@interface SharedExamplesTests_ObjC : XCTestCase; @end + +@implementation SharedExamplesTests_ObjC + +- (void)testAGroupOfThreeSharedExamplesExecutesThreeExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_SharedExamples_Spec_ObjC class]); + XCTAssert(result.hasSucceeded); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testSharedExamplesWithContextPassContextToExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_SharedExamples_ContextSpec_ObjC class]); + XCTAssert(result.hasSucceeded); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift new file mode 100644 index 0000000..5334200 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift @@ -0,0 +1,61 @@ +import XCTest +import Quick +import Nimble + +var oneExampleBeforeEachExecutedCount = 0 +var onlyPendingExamplesBeforeEachExecutedCount = 0 + +class FunctionalTests_PendingSpec_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("an example that will not run") { + expect(true).to(beFalsy()) + } + } +} +class FunctionalTests_PendingSpec: QuickSpec { + override func spec() { + xit("an example that will not run") { + expect(true).to(beFalsy()) + } + xitBehavesLike(FunctionalTests_PendingSpec_Behavior.self) { () -> Void in } + describe("a describe block containing only one enabled example") { + beforeEach { oneExampleBeforeEachExecutedCount += 1 } + it("an example that will run") {} + pending("an example that will not run") {} + } + + describe("a describe block containing only pending examples") { + beforeEach { onlyPendingExamplesBeforeEachExecutedCount += 1 } + pending("an example that will not run") {} + } + } +} + +final class PendingTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PendingTests) -> () throws -> Void)] { + return [ + ("testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail", testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail), + ("testBeforeEachOnlyRunForEnabledExamples", testBeforeEachOnlyRunForEnabledExamples), + ("testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples", testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples) + ] + } + + func testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail() { + let result = qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertTrue(result!.hasSucceeded) + } + + func testBeforeEachOnlyRunForEnabledExamples() { + oneExampleBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertEqual(oneExampleBeforeEachExecutedCount, 1) + } + + func testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples() { + onlyPendingExamplesBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertEqual(onlyPendingExamplesBeforeEachExecutedCount, 0) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift new file mode 100644 index 0000000..2b0fd77 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift @@ -0,0 +1,48 @@ +import XCTest +import Quick +import Nimble + +var specBeforeEachExecutedCount = 0 +var sharedExamplesBeforeEachExecutedCount = 0 + +class FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("a group of three shared examples with a beforeEach") { + beforeEach { sharedExamplesBeforeEachExecutedCount += 1 } + it("passes once") {} + it("passes twice") {} + it("passes three times") {} + } + } +} + +class FunctionalTests_SharedExamples_BeforeEachSpec: QuickSpec { + override func spec() { + beforeEach { specBeforeEachExecutedCount += 1 } + it("executes the spec beforeEach once") {} + itBehavesLike("a group of three shared examples with a beforeEach") + } +} + +final class SharedExamples_BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SharedExamples_BeforeEachTests) -> () throws -> Void)] { + return [ + ("testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample", testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample), + ("testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample", testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample) + ] + } + + func testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample() { + specBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.self) + XCTAssertEqual(specBeforeEachExecutedCount, 4) + } + + func testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample() { + sharedExamplesBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.self) + XCTAssertEqual(sharedExamplesBeforeEachExecutedCount, 3) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift new file mode 100644 index 0000000..8a50cc1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Quick +import Nimble + +class FunctionalTests_SharedExamples_Spec: QuickSpec { + override func spec() { + itBehavesLike("a group of three shared examples") + } +} + +class FunctionalTests_SharedExamples_ContextSpec: QuickSpec { + override func spec() { + itBehavesLike("shared examples that take a context") { ["callsite": "SharedExamplesSpec"] } + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class FunctionalTests_SharedExamples_ErrorSpec: QuickSpec { + override func spec() { + describe("error handling when misusing ordering") { + it("should throw an exception when including itBehavesLike in it block") { + expect { + itBehavesLike("a group of three shared examples") + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'itBehavesLike' cannot be used inside 'it', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif + +// Shared examples are defined in QuickTests/Fixtures +final class SharedExamplesTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SharedExamplesTests) -> () throws -> Void)] { + return [ + ("testAGroupOfThreeSharedExamplesExecutesThreeExamples", testAGroupOfThreeSharedExamplesExecutesThreeExamples), + ("testSharedExamplesWithContextPassContextToExamples", testSharedExamplesWithContextPassContextToExamples) + ] + } + + func testAGroupOfThreeSharedExamplesExecutesThreeExamples() { + let result = qck_runSpec(FunctionalTests_SharedExamples_Spec.self) + XCTAssert(result!.hasSucceeded) + XCTAssertEqual(result!.executionCount, 3) + } + + func testSharedExamplesWithContextPassContextToExamples() { + let result = qck_runSpec(FunctionalTests_SharedExamples_ContextSpec.self) + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h new file mode 100644 index 0000000..183118e --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h @@ -0,0 +1,22 @@ +@import XCTest; + +/** + Runs an XCTestSuite instance containing only the given XCTestCase subclass. + Use this to run QuickSpec subclasses from within a set of unit tests. + + Due to implicit dependencies in _XCTFailureHandler, this function raises an + exception when used in Swift to run a failing test case. + + @param specClass The class of the spec to be run. + @return An XCTestRun instance that contains information such as the number of failures, etc. + */ +extern XCTestRun * _Nullable qck_runSpec(Class _Nonnull specClass); + +/** + Runs an XCTestSuite instance containing the given XCTestCase subclasses, in the order provided. + See the documentation for `qck_runSpec` for more details. + + @param specClasses An array of QuickSpec classes, in the order they should be run. + @return An XCTestRun instance that contains information such as the number of failures, etc. + */ +extern XCTestRun * _Nullable qck_runSpecs(NSArray * _Nonnull specClasses); diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m new file mode 100644 index 0000000..a2aa78c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m @@ -0,0 +1,33 @@ +@import Quick; + +#import "QCKSpecRunner.h" +#import "XCTestObservationCenter+QCKSuspendObservation.h" +#import "World.h" + +@interface XCTest (Redeclaration) +- (XCTestRun *)run; +@end + +XCTestRun * _Nullable qck_runSuite(XCTestSuite * _Nonnull suite) { + [World sharedWorld].isRunningAdditionalSuites = YES; + + __block XCTestRun *result = nil; + [[XCTestObservationCenter sharedTestObservationCenter] qck_suspendObservationForBlock:^{ + [suite runTest]; + result = suite.testRun; + }]; + return result; +} + +XCTestRun *qck_runSpec(Class specClass) { + return qck_runSuite([XCTestSuite testSuiteForTestCaseClass:specClass]); +} + +XCTestRun * _Nullable qck_runSpecs(NSArray * _Nonnull specClasses) { + XCTestSuite *suite = [XCTestSuite testSuiteWithName:@"MySpecs"]; + for (Class specClass in specClasses) { + [suite addTest:[XCTestSuite testSuiteForTestCaseClass:specClass]]; + } + + return qck_runSuite(suite); +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h new file mode 100644 index 0000000..99e20f8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h @@ -0,0 +1,11 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QuickSpec (QuickSpec_MethodList) + ++ (NSSet *)allSelectors; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m new file mode 100644 index 0000000..c648bd1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m @@ -0,0 +1,31 @@ +#import "QuickSpec+QuickSpec_MethodList.h" +#import + + +@implementation QuickSpec (QuickSpec_MethodList) + +/** + * This method will instantiate an instance of the class on which it is called, + * returning a list of selector names for it. + * + * @warning Only intended to be used in test assertions! + * + * @return a set of NSStrings representing the list of selectors it contains + */ ++ (NSSet *)allSelectors { + QuickSpec *specInstance = [[[self class] alloc] init]; + NSMutableSet *allSelectors = [NSMutableSet set]; + + unsigned int methodCount = 0; + Method *mlist = class_copyMethodList(object_getClass(specInstance), &methodCount); + + for(unsigned int i = 0; i < methodCount; i++) { + SEL selector = method_getName(mlist[i]); + [allSelectors addObject:NSStringFromSelector(selector)]; + } + + free(mlist); + return [allSelectors copy]; +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h new file mode 100644 index 0000000..301c5d5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h @@ -0,0 +1,2 @@ +#import "QCKSpecRunner.h" +#import "QuickSpec+QuickSpec_MethodList.h" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h new file mode 100644 index 0000000..d69f808 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h @@ -0,0 +1,20 @@ +#import + +/** + Add the ability to temporarily disable internal XCTest execution observation in + order to run isolated XCTestSuite instances while the QuickTests test suite is running. + */ +@interface XCTestObservationCenter (QCKSuspendObservation) + +/** + Suspends test suite observation for XCTest-provided observers for the duration that + the block is executing. Any test suites that are executed within the block do not + generate any log output. Failures are still reported. + + Use this method to run XCTestSuite objects while another XCTestSuite is running. + Without this method, tests fail with the message: "Timed out waiting for IDE + barrier message to complete" or "Unexpected TestSuiteDidStart". + */ +- (void)qck_suspendObservationForBlock:(void (^)(void))block; + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m new file mode 100644 index 0000000..1a32e10 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m @@ -0,0 +1,54 @@ +@import XCTest; +#import + +@interface XCTestObservationCenter (Redeclaration) +- (id)observers; +- (void)removeTestObserver:(id)testObserver; +@end + +@implementation XCTestObservationCenter (QCKSuspendObservation) + +/// This allows us to only suspend observation for observers by provided by Apple +/// as a part of the XCTest framework. In particular it is important that we not +/// suspend the observer added by Nimble, otherwise it is unable to properly +/// report assertion failures. +static BOOL (^isFromApple)(id) = ^BOOL(id observer){ + return [[NSBundle bundleForClass:[observer class]].bundleIdentifier containsString:@"com.apple.dt.XCTest"]; +}; + +- (void)qck_suspendObservationForBlock:(void (^)(void))block { + id originalObservers = [[self observers] copy]; + NSMutableArray *suspendedObservers = [NSMutableArray new]; + + for (id observer in originalObservers) { + if (isFromApple(observer)) { + [suspendedObservers addObject:observer]; + + if ([self respondsToSelector:@selector(removeTestObserver:)]) { + [self removeTestObserver:observer]; + } + else if ([[self observers] respondsToSelector:@selector(removeObject:)]) { + [[self observers] removeObject:observer]; + } + else { + NSAssert(NO, @"unexpected type: unable to remove observers: %@", originalObservers); + } + } + } + + @try { + block(); + } + @finally { + for (id observer in suspendedObservers) { + if ([[self observers] respondsToSelector:@selector(addObject:)]) { + [[self observers] addObject:observer]; + } + else if ([self respondsToSelector:@selector(addTestObserver:)]) { + [self addTestObserver:observer]; + } + } + } +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m new file mode 100644 index 0000000..ace4577 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m @@ -0,0 +1,12 @@ +#import +#import + +@interface QuickConfigurationTests : XCTestCase; @end + +@implementation QuickConfigurationTests + +- (void)testInitThrows { + XCTAssertThrowsSpecificNamed([QuickConfiguration new], NSException, NSInternalInconsistencyException); +} + +@end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/release b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/release new file mode 100755 index 0000000..26409c4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/release @@ -0,0 +1,182 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Quick +PODSPEC=Quick.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=.release-changes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + rm $RELEASE_NOTES + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "Pushing to pod trunk..." + +$POD trunk push "$PODSPEC" + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for Github styling." +echo " - Announce!" + +open "https://github.com/Quick/Quick/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-linux b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-linux new file mode 100755 index 0000000..279cd88 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-linux @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e + +# See: https://github.com/kylef/swiftenv/wiki/Travis-CI +curl -sL https://gist.github.com/kylef/5c0475ff02b7c7671d2a/raw/621ef9b29bbb852fdfd2e10ed147b321d792c1e4/swiftenv-install.sh | bash diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-macos b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-macos new file mode 100755 index 0000000..64edf92 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-install-macos @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +set -e + +git submodule update --init --recursive diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-linux b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-linux new file mode 100755 index 0000000..7a6558d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-linux @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +. ~/.swiftenv/init +rake test:swiftpm diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-macos b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-macos new file mode 100755 index 0000000..ac60f1c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Quick/script/travis-script-macos @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +if [ "$PODSPEC" ]; then + TASK="podspec:lint" +else + TASK="test:$PLATFORM" +fi + +echo "Executing rake task: $TASK" +rake "$TASK" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.gitignore b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.gitignore new file mode 100644 index 0000000..29471cb --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +xcuserdata +*.xcuserdatad +*.xccheckout +*.mode* +*.pbxuser + +Carthage/Build +.build diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.swift-version b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.swift-version new file mode 100644 index 0000000..7d5c902 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.swift-version @@ -0,0 +1 @@ +4.1 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.travis.yml b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.travis.yml new file mode 100644 index 0000000..6c0cd1a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/.travis.yml @@ -0,0 +1,62 @@ +branches: + only: + - master + +matrix: + include: + - script: + - set -o pipefail + - xcodebuild $XCODE_ACTION -scheme Result-Mac | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-iOS -sdk iphonesimulator -destination "name=iPhone SE" | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-tvOS -sdk appletvsimulator -destination "name=Apple TV" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + - gem update cocoapods && rm .swift-version && pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode9.2 + language: objective-c + - script: + - set -o pipefail + - xcodebuild $XCODE_ACTION -scheme Result-Mac | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-iOS -sdk iphonesimulator -destination "name=iPhone SE" | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-tvOS -sdk appletvsimulator -destination "name=Apple TV" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + - rm .swift-version && pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode9.3 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode9.2 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode9.3 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: + - JOB=Linux + sudo: required + dist: trusty + language: generic + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + +notifications: + email: false diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/CONTRIBUTING.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/CONTRIBUTING.md new file mode 100644 index 0000000..f58c3fa --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/CONTRIBUTING.md @@ -0,0 +1,23 @@ +We love that you're interested in contributing to this project! + +To make the process as painless as possible, we have just a couple of guidelines +that should make life easier for everyone involved. + +## Prefer Pull Requests + +If you know exactly how to implement the feature being suggested or fix the bug +being reported, please open a pull request instead of an issue. Pull requests are easier than +patches or inline code blocks for discussing and merging the changes. + +If you can't make the change yourself, please open an issue after making sure +that one isn't already logged. + +## Contributing Code + +Fork this repository, make it awesomer (preferably in a branch named for the +topic), send a pull request! + +All code contributions should match our [coding +conventions](https://github.com/github/swift-style-guide). + +Thanks for contributing! :boom::camel: diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/LICENSE b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/LICENSE new file mode 100644 index 0000000..3026ee1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Rob Rix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Package.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Package.swift new file mode 100644 index 0000000..c93a688 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version:4.0 +import PackageDescription + +let package = Package( + name: "Result", + products: [ + .library(name: "Result", targets: ["Result"]), + ], + targets: [ + .target(name: "Result", dependencies: [], path: "Result"), + .testTarget(name: "ResultTests", dependencies: ["Result"]), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/README.md new file mode 100644 index 0000000..bf85e78 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/README.md @@ -0,0 +1,113 @@ +# Result + +[![Build Status](https://travis-ci.org/antitypical/Result.svg?branch=master)](https://travis-ci.org/antitypical/Result) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![CocoaPods](https://img.shields.io/cocoapods/v/Result.svg)](https://cocoapods.org/) +[![Reference Status](https://www.versioneye.com/objective-c/result/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/result/references) + +This is a Swift µframework providing `Result`. + +`Result` values are either successful (wrapping `Value`) or failed (wrapping `Error`). This is similar to Swift’s native `Optional` type: `success` is like `some`, and `failure` is like `none` except with an associated `Error` value. The addition of an associated `Error` allows errors to be passed along for logging or displaying to the user. + +Using this µframework instead of rolling your own `Result` type allows you to easily interface with other frameworks that also use `Result`. + +## Use + +Use `Result` whenever an operation has the possibility of failure. Consider the following example of a function that tries to extract a `String` for a given key from a JSON `Dictionary`. + +```swift +typealias JSONObject = [String: Any] + +enum JSONError: Error { + case noSuchKey(String) + case typeMismatch +} + +func stringForKey(json: JSONObject, key: String) -> Result { + guard let value = json[key] else { + return .failure(.noSuchKey(key)) + } + + if let value = value as? String { + return .success(value) + } + else { + return .failure(.typeMismatch) + } +} +``` + +This function provides a more robust wrapper around the default subscripting provided by `Dictionary`. Rather than return `Any?`, it returns a `Result` that either contains the `String` value for the given key, or an `ErrorType` detailing what went wrong. + +One simple way to handle a `Result` is to deconstruct it using a `switch` statement. + +```swift +switch stringForKey(json, key: "email") { + +case let .success(email): + print("The email is \(email)") + +case let .failure(.noSuchKey(key)): + print("\(key) is not a valid key") + +case .failure(.typeMismatch): + print("Didn't have the right type") +} +``` + +Using a `switch` statement allows powerful pattern matching, and ensures all possible results are covered. Swift 2.0 offers new ways to deconstruct enums like the `if-case` statement, but be wary as such methods do not ensure errors are handled. + +Other methods available for processing `Result` are detailed in the [API documentation](http://cocoadocs.org/docsets/Result/). + +## Result vs. Throws + +Swift 2.0 introduces error handling via throwing and catching `Error`. `Result` accomplishes the same goal by encapsulating the result instead of hijacking control flow. The `Result` abstraction enables powerful functionality such as `map` and `flatMap`, making `Result` more composable than `throw`. + +Since dealing with APIs that throw is common, you can convert such functions into a `Result` by using the `materialize` method. Conversely, a `Result` can be used to throw an error by calling `dematerialize`. + +## Higher Order Functions + +`map` and `flatMap` operate the same as `Optional.map` and `Optional.flatMap` except they apply to `Result`. + +`map` transforms a `Result` into a `Result` of a new type. It does this by taking a function that transforms the `Value` type into a new value. This transformation is only applied in the case of a `success`. In the case of a `failure`, the associated error is re-wrapped in the new `Result`. + +```swift +// transforms a Result to a Result +let idResult = intForKey(json, key:"id").map { id in String(id) } +``` + +Here, the final result is either the id as a `String`, or carries over the `failure` from the previous result. + +`flatMap` is similar to `map` in that it transforms the `Result` into another `Result`. However, the function passed into `flatMap` must return a `Result`. + +An in depth discussion of `map` and `flatMap` is beyond the scope of this documentation. If you would like a deeper understanding, read about functors and monads. This article is a good place to [start](http://www.javiersoto.me/post/106875422394). + +## Integration + +### Carthage + +1. Add this repository as a submodule and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies. +2. Drag `Result.xcodeproj` into your project or workspace. +3. Link your target against `Result.framework`. +4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Result.) + +### Cocoapods + +```ruby +pod 'Result', '~> 3.0.0' +``` + +### Swift Package Manager + +```swift +import PackageDescription + +let package = Package( + name: "MyProject", + targets: [], + dependencies: [ + .Package(url: "https://github.com/antitypical/Result.git", + majorVersion: 3) + ] +) +``` diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.podspec b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.podspec new file mode 100644 index 0000000..09e59f9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.podspec @@ -0,0 +1,19 @@ +Pod::Spec.new do |s| + s.name = 'Result' + s.version = '4.0.0' + s.summary = 'Swift type modelling the success/failure of arbitrary operations' + + s.homepage = 'https://github.com/antitypical/Result' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { 'Rob Rix' => 'rob.rix@github.com' } + s.source = { :git => 'https://github.com/antitypical/Result.git', :tag => s.version } + s.source_files = 'Result/*.swift' + s.requires_arc = true + s.ios.deployment_target = '8.0' + s.osx.deployment_target = '10.9' + s.watchos.deployment_target = '2.0' + s.tvos.deployment_target = '9.0' + + s.swift_version = '4.0' + s.cocoapods_version = '>= 1.4.0' +end diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj new file mode 100644 index 0000000..651d0ca --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj @@ -0,0 +1,1066 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + 57FCDE421BA280DC00130C48 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + 57FCDE561BA2814300130C48 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57FCDE471BA280DC00130C48 /* Result.framework */; }; + CD333EF21ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF31ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF41ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF51ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF71ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EF81ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EF91ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EFA1ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EFC1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333EFD1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333EFE1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333F001ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + CD333F011ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + CD333F021ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + D035799B1B2B788F005D26AE /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D035799E1B2B788F005D26AE /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D454805D1A9572F5009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D45480681A9572F5009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D45480571A9572F5009D7229 /* Result.framework */; }; + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D45480881A957362009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D454807D1A957361009D7229 /* Result.framework */; }; + D45480971A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480981A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D454809A1A9574BB009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 57FCDE571BA2814A00130C48 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 57FCDE3C1BA280DC00130C48; + remoteInfo = "Result-tvOS"; + }; + D45480691A9572F5009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D45480561A9572F5009D7229; + remoteInfo = Result; + }; + D45480891A957362009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D454807C1A957361009D7229; + remoteInfo = "Result-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 57FCDE471BA280DC00130C48 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CD261ACF1DECFE3400A8863C /* LinuxMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = ../LinuxMain.swift; sourceTree = ""; }; + CD333EF11ED50550004D9C5D /* NoError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoError.swift; sourceTree = ""; }; + CD333EF61ED505D7004D9C5D /* AnyError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyError.swift; sourceTree = ""; }; + CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoErrorTests.swift; sourceTree = ""; }; + CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyErrorTests.swift; sourceTree = ""; }; + D03579A31B2B788F005D26AE /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480571A9572F5009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D454805B1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454805C1A9572F5009D7229 /* Result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Result.h; sourceTree = ""; }; + D45480671A9572F5009D7229 /* Result-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D454806D1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454806E1A9572F5009D7229 /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = ""; }; + D454807D1A957361009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480871A957362009D7229 /* Result-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480961A957465009D7229 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; + E93621451B35596200948F2A /* ResultProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultProtocol.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 57FCDE401BA280DC00130C48 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4E1BA280E000130C48 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE561BA2814300130C48 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799C1B2B788F005D26AE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480531A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480641A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480681A9572F5009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480791A957361009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480841A957362009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480881A957362009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D454804D1A9572F5009D7229 = { + isa = PBXGroup; + children = ( + D45480591A9572F5009D7229 /* Result */, + D454806B1A9572F5009D7229 /* ResultTests */, + D45480581A9572F5009D7229 /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D45480581A9572F5009D7229 /* Products */ = { + isa = PBXGroup; + children = ( + D45480571A9572F5009D7229 /* Result.framework */, + D45480671A9572F5009D7229 /* Result-MacTests.xctest */, + D454807D1A957361009D7229 /* Result.framework */, + D45480871A957362009D7229 /* Result-iOSTests.xctest */, + D03579A31B2B788F005D26AE /* Result.framework */, + 57FCDE471BA280DC00130C48 /* Result.framework */, + 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D45480591A9572F5009D7229 /* Result */ = { + isa = PBXGroup; + children = ( + CD333EF61ED505D7004D9C5D /* AnyError.swift */, + CD333EF11ED50550004D9C5D /* NoError.swift */, + D454805C1A9572F5009D7229 /* Result.h */, + D45480961A957465009D7229 /* Result.swift */, + E93621451B35596200948F2A /* ResultProtocol.swift */, + D454805A1A9572F5009D7229 /* Supporting Files */, + ); + path = Result; + sourceTree = ""; + }; + D454805A1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D454805B1A9572F5009D7229 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D454806B1A9572F5009D7229 /* ResultTests */ = { + isa = PBXGroup; + children = ( + CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */, + CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */, + D454806E1A9572F5009D7229 /* ResultTests.swift */, + D454806C1A9572F5009D7229 /* Supporting Files */, + ); + name = ResultTests; + path = Tests/ResultTests; + sourceTree = ""; + }; + D454806C1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D454806D1A9572F5009D7229 /* Info.plist */, + CD261ACF1DECFE3400A8863C /* LinuxMain.swift */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 57FCDE411BA280DC00130C48 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE421BA280DC00130C48 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799D1B2B788F005D26AE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D035799E1B2B788F005D26AE /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480541A9572F5009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454805D1A9572F5009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807A1A957361009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454809A1A9574BB009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 57FCDE3C1BA280DC00130C48 /* Result-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57FCDE441BA280DC00130C48 /* Build configuration list for PBXNativeTarget "Result-tvOS" */; + buildPhases = ( + 57FCDE3D1BA280DC00130C48 /* Sources */, + 57FCDE401BA280DC00130C48 /* Frameworks */, + 57FCDE411BA280DC00130C48 /* Headers */, + 57FCDE431BA280DC00130C48 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-tvOS"; + productName = "Result-iOS"; + productReference = 57FCDE471BA280DC00130C48 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + 57FCDE491BA280E000130C48 /* Result-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57FCDE511BA280E000130C48 /* Build configuration list for PBXNativeTarget "Result-tvOSTests" */; + buildPhases = ( + 57FCDE4C1BA280E000130C48 /* Sources */, + 57FCDE4E1BA280E000130C48 /* Frameworks */, + 57FCDE501BA280E000130C48 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 57FCDE581BA2814A00130C48 /* PBXTargetDependency */, + ); + name = "Result-tvOSTests"; + productName = "Result-iOSTests"; + productReference = 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D03579991B2B788F005D26AE /* Result-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D03579A01B2B788F005D26AE /* Build configuration list for PBXNativeTarget "Result-watchOS" */; + buildPhases = ( + D035799A1B2B788F005D26AE /* Sources */, + D035799C1B2B788F005D26AE /* Frameworks */, + D035799D1B2B788F005D26AE /* Headers */, + D035799F1B2B788F005D26AE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-watchOS"; + productName = Result; + productReference = D03579A31B2B788F005D26AE /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480561A9572F5009D7229 /* Result-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */; + buildPhases = ( + D45480521A9572F5009D7229 /* Sources */, + D45480531A9572F5009D7229 /* Frameworks */, + D45480541A9572F5009D7229 /* Headers */, + D45480551A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-Mac"; + productName = Result; + productReference = D45480571A9572F5009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480661A9572F5009D7229 /* Result-MacTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */; + buildPhases = ( + D45480631A9572F5009D7229 /* Sources */, + D45480641A9572F5009D7229 /* Frameworks */, + D45480651A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454806A1A9572F5009D7229 /* PBXTargetDependency */, + ); + name = "Result-MacTests"; + productName = ResultTests; + productReference = D45480671A9572F5009D7229 /* Result-MacTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D454807C1A957361009D7229 /* Result-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */; + buildPhases = ( + D45480781A957361009D7229 /* Sources */, + D45480791A957361009D7229 /* Frameworks */, + D454807A1A957361009D7229 /* Headers */, + D454807B1A957361009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-iOS"; + productName = "Result-iOS"; + productReference = D454807D1A957361009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480861A957362009D7229 /* Result-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */; + buildPhases = ( + D45480831A957362009D7229 /* Sources */, + D45480841A957362009D7229 /* Frameworks */, + D45480851A957362009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454808A1A957362009D7229 /* PBXTargetDependency */, + ); + name = "Result-iOSTests"; + productName = "Result-iOSTests"; + productReference = D45480871A957362009D7229 /* Result-iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D454804E1A9572F5009D7229 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + 57FCDE3C1BA280DC00130C48 = { + LastSwiftMigration = 0920; + }; + 57FCDE491BA280E000130C48 = { + LastSwiftMigration = 0920; + }; + D03579991B2B788F005D26AE = { + LastSwiftMigration = 0920; + }; + D45480561A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0900; + }; + D45480661A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0900; + }; + D454807C1A957361009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0920; + }; + D45480861A957362009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0920; + }; + }; + }; + buildConfigurationList = D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D454804D1A9572F5009D7229; + productRefGroup = D45480581A9572F5009D7229 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D45480561A9572F5009D7229 /* Result-Mac */, + D45480661A9572F5009D7229 /* Result-MacTests */, + D454807C1A957361009D7229 /* Result-iOS */, + D45480861A957362009D7229 /* Result-iOSTests */, + 57FCDE3C1BA280DC00130C48 /* Result-tvOS */, + 57FCDE491BA280E000130C48 /* Result-tvOSTests */, + D03579991B2B788F005D26AE /* Result-watchOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 57FCDE431BA280DC00130C48 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE501BA280E000130C48 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799F1B2B788F005D26AE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480551A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480651A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807B1A957361009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480851A957362009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 57FCDE3D1BA280DC00130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF41ED50550004D9C5D /* NoError.swift in Sources */, + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */, + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */, + CD333EF91ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4C1BA280E000130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */, + CD333F021ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFE1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799A1B2B788F005D26AE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF51ED50550004D9C5D /* NoError.swift in Sources */, + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */, + D035799B1B2B788F005D26AE /* Result.swift in Sources */, + CD333EFA1ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480521A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF21ED50550004D9C5D /* NoError.swift in Sources */, + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480971A957465009D7229 /* Result.swift in Sources */, + CD333EF71ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480631A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */, + CD333F001ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFC1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480781A957361009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF31ED50550004D9C5D /* NoError.swift in Sources */, + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480981A957465009D7229 /* Result.swift in Sources */, + CD333EF81ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480831A957362009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */, + CD333F011ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFD1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 57FCDE581BA2814A00130C48 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 57FCDE3C1BA280DC00130C48 /* Result-tvOS */; + targetProxy = 57FCDE571BA2814A00130C48 /* PBXContainerItemProxy */; + }; + D454806A1A9572F5009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D45480561A9572F5009D7229 /* Result-Mac */; + targetProxy = D45480691A9572F5009D7229 /* PBXContainerItemProxy */; + }; + D454808A1A957362009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D454807C1A957361009D7229 /* Result-iOS */; + targetProxy = D45480891A957362009D7229 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 57FCDE451BA280DC00130C48 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=appletvsimulator*]" = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 57FCDE461BA280DC00130C48 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=appletvsimulator*]" = ""; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 57FCDE521BA280E000130C48 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + }; + name = Debug; + }; + 57FCDE531BA280E000130C48 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D03579A11B2B788F005D26AE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchsimulator*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = watchos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + D03579A21B2B788F005D26AE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchsimulator*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = watchos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + D45480701A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + D45480711A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + D45480731A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + D45480741A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + D45480761A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D45480771A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D45480901A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D45480911A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D45480921A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + D45480931A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 57FCDE441BA280DC00130C48 /* Build configuration list for PBXNativeTarget "Result-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 57FCDE451BA280DC00130C48 /* Debug */, + 57FCDE461BA280DC00130C48 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 57FCDE511BA280E000130C48 /* Build configuration list for PBXNativeTarget "Result-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 57FCDE521BA280E000130C48 /* Debug */, + 57FCDE531BA280E000130C48 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D03579A01B2B788F005D26AE /* Build configuration list for PBXNativeTarget "Result-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D03579A11B2B788F005D26AE /* Debug */, + D03579A21B2B788F005D26AE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480701A9572F5009D7229 /* Debug */, + D45480711A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480731A9572F5009D7229 /* Debug */, + D45480741A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480761A9572F5009D7229 /* Debug */, + D45480771A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480901A957362009D7229 /* Debug */, + D45480911A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480921A957362009D7229 /* Debug */, + D45480931A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D454804E1A9572F5009D7229 /* Project object */; +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..10cf711 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme new file mode 100644 index 0000000..eee4090 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme new file mode 100644 index 0000000..d669e9b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme new file mode 100644 index 0000000..e337798 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme new file mode 100644 index 0000000..59371bc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/AnyError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/AnyError.swift new file mode 100644 index 0000000..ee018d2 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/AnyError.swift @@ -0,0 +1,46 @@ +import Foundation + +/// A type-erased error which wraps an arbitrary error instance. This should be +/// useful for generic contexts. +public struct AnyError: Swift.Error { + /// The underlying error. + public let error: Swift.Error + + public init(_ error: Swift.Error) { + if let anyError = error as? AnyError { + self = anyError + } else { + self.error = error + } + } +} + +extension AnyError: ErrorConvertible { + public static func error(from error: Error) -> AnyError { + return AnyError(error) + } +} + +extension AnyError: CustomStringConvertible { + public var description: String { + return String(describing: error) + } +} + +extension AnyError: LocalizedError { + public var errorDescription: String? { + return error.localizedDescription + } + + public var failureReason: String? { + return (error as? LocalizedError)?.failureReason + } + + public var helpAnchor: String? { + return (error as? LocalizedError)?.helpAnchor + } + + public var recoverySuggestion: String? { + return (error as? LocalizedError)?.recoverySuggestion + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Info.plist new file mode 100644 index 0000000..52221a4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Rob Rix. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/NoError.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/NoError.swift new file mode 100644 index 0000000..a919f51 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/NoError.swift @@ -0,0 +1,10 @@ +/// An “error” that is impossible to construct. +/// +/// This can be used to describe `Result`s where failures will never +/// be generated. For example, `Result` describes a result that +/// contains an `Int`eger and is guaranteed never to be a `failure`. +public enum NoError: Swift.Error, Equatable { + public static func ==(lhs: NoError, rhs: NoError) -> Bool { + return true + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.h b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.h new file mode 100644 index 0000000..4742701 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.h @@ -0,0 +1,8 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// Project version number for Result. +extern double ResultVersionNumber; + +/// Project version string for Result. +extern const unsigned char ResultVersionString[]; + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.swift new file mode 100644 index 0000000..de0330a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/Result.swift @@ -0,0 +1,196 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// An enum representing either a failure with an explanatory error, or a success with a result value. +public enum Result: ResultProtocol, CustomStringConvertible, CustomDebugStringConvertible { + case success(Value) + case failure(Error) + + // MARK: Constructors + + /// Constructs a success wrapping a `value`. + public init(value: Value) { + self = .success(value) + } + + /// Constructs a failure wrapping an `error`. + public init(error: Error) { + self = .failure(error) + } + + /// Constructs a result from an `Optional`, failing with `Error` if `nil`. + public init(_ value: Value?, failWith: @autoclosure () -> Error) { + self = value.map(Result.success) ?? .failure(failWith()) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(_ f: @autoclosure () throws -> Value) { + self.init(attempt: f) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(attempt f: () throws -> Value) { + do { + self = .success(try f()) + } catch var error { + if Error.self == AnyError.self { + error = AnyError(error) + } + self = .failure(error as! Error) + } + } + + // MARK: Deconstruction + + /// Returns the value from `success` Results or `throw`s the error. + public func dematerialize() throws -> Value { + switch self { + case let .success(value): + return value + case let .failure(error): + throw error + } + } + + /// Case analysis for Result. + /// + /// Returns the value produced by applying `ifFailure` to `failure` Results, or `ifSuccess` to `success` Results. + public func analysis(ifSuccess: (Value) -> Result, ifFailure: (Error) -> Result) -> Result { + switch self { + case let .success(value): + return ifSuccess(value) + case let .failure(value): + return ifFailure(value) + } + } + + // MARK: Errors + + /// The domain for errors constructed by Result. + public static var errorDomain: String { return "com.antitypical.Result" } + + /// The userInfo key for source functions in errors constructed by Result. + public static var functionKey: String { return "\(errorDomain).function" } + + /// The userInfo key for source file paths in errors constructed by Result. + public static var fileKey: String { return "\(errorDomain).file" } + + /// The userInfo key for source file line numbers in errors constructed by Result. + public static var lineKey: String { return "\(errorDomain).line" } + + /// Constructs an error. + public static func error(_ message: String? = nil, function: String = #function, file: String = #file, line: Int = #line) -> NSError { + var userInfo: [String: Any] = [ + functionKey: function, + fileKey: file, + lineKey: line, + ] + + if let message = message { + userInfo[NSLocalizedDescriptionKey] = message + } + + return NSError(domain: errorDomain, code: 0, userInfo: userInfo) + } + + + // MARK: CustomStringConvertible + + public var description: String { + switch self { + case let .success(value): return ".success(\(value))" + case let .failure(error): return ".failure(\(error))" + } + } + + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + return description + } + + // MARK: ResultProtocol + public var result: Result { + return self + } +} + +extension Result where Error == AnyError { + /// Constructs a result from an expression that uses `throw`, failing with `AnyError` if throws. + public init(_ f: @autoclosure () throws -> Value) { + self.init(attempt: f) + } + + /// Constructs a result from a closure that uses `throw`, failing with `AnyError` if throws. + public init(attempt f: () throws -> Value) { + do { + self = .success(try f()) + } catch { + self = .failure(AnyError(error)) + } + } +} + +// MARK: - Derive result from failable closure + +@available(*, deprecated, renamed: "Result.init(attempt:)") +public func materialize(_ f: () throws -> T) -> Result { + return Result(attempt: f) +} + +@available(*, deprecated, renamed: "Result.init(_:)") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + return Result(f) +} + +// MARK: - ErrorConvertible conformance + +extension NSError: ErrorConvertible { + public static func error(from error: Swift.Error) -> Self { + func cast(_ error: Swift.Error) -> T { + return error as! T + } + + return cast(error) + } +} + +// MARK: - migration support + +@available(*, unavailable, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: () throws -> T) -> Result { + fatalError() +} + +@available(*, unavailable, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + fatalError() +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// Constructs a `Result` with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.: +/// +/// Result.try { NSData(contentsOfURL: URL, options: .dataReadingMapped, error: $0) } +@available(*, unavailable, message: "This has been removed. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.") +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> T?) -> Result { + fatalError() +} + +/// Constructs a `Result` with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.: +/// +/// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) } +@available(*, unavailable, message: "This has been removed. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.") +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> Bool) -> Result<(), NSError> { + fatalError() +} + +#endif + +// MARK: - + +import Foundation diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/ResultProtocol.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/ResultProtocol.swift new file mode 100644 index 0000000..703ad89 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result/ResultProtocol.swift @@ -0,0 +1,152 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// A protocol that can be used to constrain associated types as `Result`. +public protocol ResultProtocol { + associatedtype Value + associatedtype Error: Swift.Error + + init(value: Value) + init(error: Error) + + var result: Result { get } +} + +public extension Result { + /// Returns the value if self represents a success, `nil` otherwise. + public var value: Value? { + switch self { + case let .success(value): return value + case .failure: return nil + } + } + + /// Returns the error if self represents a failure, `nil` otherwise. + public var error: Error? { + switch self { + case .success: return nil + case let .failure(error): return error + } + } + + /// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors. + public func map(_ transform: (Value) -> U) -> Result { + return flatMap { .success(transform($0)) } + } + + /// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. + public func flatMap(_ transform: (Value) -> Result) -> Result { + switch self { + case let .success(value): return transform(value) + case let .failure(error): return .failure(error) + } + } + + /// Returns a Result with a tuple of the receiver and `other` values if both + /// are `Success`es, or re-wrapping the error of the earlier `Failure`. + public func fanout(_ other: @autoclosure () -> Result) -> Result<(Value, U), Error> { + return self.flatMap { left in other().map { right in (left, right) } } + } + + /// Returns a new Result by mapping `Failure`'s values using `transform`, or re-wrapping `Success`es’ values. + public func mapError(_ transform: (Error) -> Error2) -> Result { + return flatMapError { .failure(transform($0)) } + } + + /// Returns the result of applying `transform` to `Failure`’s errors, or re-wrapping `Success`es’ values. + public func flatMapError(_ transform: (Error) -> Result) -> Result { + switch self { + case let .success(value): return .success(value) + case let .failure(error): return transform(error) + } + } + + /// Returns a new Result by mapping `Success`es’ values using `success`, and by mapping `Failure`'s values using `failure`. + public func bimap(success: (Value) -> U, failure: (Error) -> Error2) -> Result { + switch self { + case let .success(value): return .success(success(value)) + case let .failure(error): return .failure(failure(error)) + } + } +} + +public extension Result { + + // MARK: Higher-order functions + + /// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??` + public func recover(_ value: @autoclosure () -> Value) -> Value { + return self.value ?? value() + } + + /// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??` + public func recover(with result: @autoclosure () -> Result) -> Result { + switch self { + case .success: return self + case .failure: return result() + } + } +} + +/// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s. +public protocol ErrorConvertible: Swift.Error { + static func error(from error: Swift.Error) -> Self +} + +public extension Result where Error: ErrorConvertible { + + /// Returns the result of applying `transform` to `Success`es’ values, or wrapping thrown errors. + public func tryMap(_ transform: (Value) throws -> U) -> Result { + return flatMap { value in + do { + return .success(try transform(value)) + } + catch { + let convertedError = Error.error(from: error) + // Revisit this in a future version of Swift. https://twitter.com/jckarter/status/672931114944696321 + return .failure(convertedError) + } + } + } +} + +// MARK: - Operators + +extension Result where Value: Equatable, Error: Equatable { + /// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal. + public static func ==(left: Result, right: Result) -> Bool { + if let left = left.value, let right = right.value { + return left == right + } else if let left = left.error, let right = right.error { + return left == right + } + return false + } +} + +#if swift(>=4.1) + extension Result: Equatable where Value: Equatable, Error: Equatable { } +#else + extension Result where Value: Equatable, Error: Equatable { + /// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. + public static func !=(left: Result, right: Result) -> Bool { + return !(left == right) + } + } +#endif + +extension Result { + /// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. + public static func ??(left: Result, right: @autoclosure () -> Value) -> Value { + return left.recover(right()) + } + + /// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. + public static func ??(left: Result, right: @autoclosure () -> Result) -> Result { + return left.recover(with: right()) + } +} + +// MARK: - migration support + +@available(*, unavailable, renamed: "ErrorConvertible") +public protocol ErrorProtocolConvertible: ErrorConvertible {} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/LinuxMain.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/LinuxMain.swift new file mode 100644 index 0000000..ec2c509 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +import ResultTests + +var tests = [XCTestCaseEntry]() +tests += ResultTests.__allTests() + +XCTMain(tests) diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift new file mode 100644 index 0000000..65a2661 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift @@ -0,0 +1,12 @@ +import Foundation +import XCTest +import Result + +final class AnyErrorTests: XCTestCase { + func testAnyError() { + let error = Error.a + let anyErrorFromError = AnyError(error) + let anyErrorFromAnyError = AnyError(anyErrorFromError) + XCTAssertTrue(anyErrorFromError == anyErrorFromAnyError) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist new file mode 100644 index 0000000..18f6dd6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift new file mode 100644 index 0000000..61bc107 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift @@ -0,0 +1,11 @@ +import Foundation +import XCTest +import Result + +final class NoErrorTests: XCTestCase { + func testEquatable() { + let foo = Result(1) + let bar = Result(1) + XCTAssertTrue(foo == bar) + } +} diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift new file mode 100644 index 0000000..f7fb38c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift @@ -0,0 +1,256 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +final class ResultTests: XCTestCase { + func testMapTransformsSuccesses() { + XCTAssertEqual(success.map { $0.count } ?? 0, 7) + } + + func testMapRewrapsFailures() { + XCTAssertEqual(failure.map { $0.count } ?? 0, 0) + } + + func testInitOptionalSuccess() { + XCTAssert(Result("success" as String?, failWith: error) == success) + } + + func testInitOptionalFailure() { + XCTAssert(Result(nil, failWith: error) == failure) + } + + func testFanout() { + let resultSuccess = success.fanout(success) + if let (x, y) = resultSuccess.value { + XCTAssertTrue(x == "success" && y == "success") + } else { + XCTFail() + } + + let resultFailureBoth = failure.fanout(failure2) + XCTAssert(resultFailureBoth.error == error) + + let resultFailureLeft = failure.fanout(success) + XCTAssert(resultFailureLeft.error == error) + + let resultFailureRight = success.fanout(failure2) + XCTAssert(resultFailureRight.error == error2) + } + + func testBimapTransformsSuccesses() { + XCTAssertEqual(success.bimap( + success: { $0.count }, + failure: { $0 } + ) ?? 0, 7) + } + + func testBimapTransformsFailures() { + XCTAssert(failure.bimap( + success: { $0 }, + failure: { _ in error2 } + ) == failure2) + } + + // MARK: Errors + + func testErrorsIncludeTheSourceFile() { + let file = #file + XCTAssert(Result<(), NSError>.error().file == file) + } + + func testErrorsIncludeTheSourceLine() { + let (line, error) = (#line, Result<(), NSError>.error()) + XCTAssertEqual(error.line ?? -1, line) + } + + func testErrorsIncludeTheCallingFunction() { + let function = #function + XCTAssert(Result<(), NSError>.error().function == function) + } + + func testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError() { + XCTAssertEqual(error.errorDescription, "localized description") + XCTAssertEqual(error.localizedDescription, "localized description") + XCTAssertEqual(error3.errorDescription, "localized description") + XCTAssertEqual(error3.localizedDescription, "localized description") + } + + func testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError() { + XCTAssertEqual(error.failureReason, "failure reason") + } + + func testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError() { + XCTAssertEqual(error.recoverySuggestion, "recovery suggestion") + } + + func testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError() { + XCTAssertEqual(error.helpAnchor, "help anchor") + } + + // MARK: Try - Catch + + func testTryCatchProducesSuccesses() { + let result: Result = Result(try tryIsSuccess("success")) + XCTAssert(result == success) + } + + func testTryCatchProducesFailures() { + let result: Result = Result(try tryIsSuccess(nil)) + XCTAssert(result.error == error) + } + + func testTryCatchWithFunctionProducesSuccesses() { + let function = { try tryIsSuccess("success") } + + let result: Result = Result(attempt: function) + XCTAssert(result == success) + } + + func testTryCatchWithFunctionCatchProducesFailures() { + let function = { try tryIsSuccess(nil) } + + let result: Result = Result(attempt: function) + XCTAssert(result.error == error) + } + + func testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures() { + let nsError = NSError(domain: "", code: 0) + let function: () throws -> String = { throw nsError } + + let result: Result = Result(attempt: function) + XCTAssert(result.error == AnyError(nsError)) + } + + func testMaterializeProducesSuccesses() { + let result1: Result = Result(try tryIsSuccess("success")) + XCTAssert(result1 == success) + + let result2: Result = Result(attempt: { try tryIsSuccess("success") }) + XCTAssert(result2 == success) + } + + func testMaterializeProducesFailures() { + let result1: Result = Result(try tryIsSuccess(nil)) + XCTAssert(result1.error == error) + + let result2: Result = Result(attempt: { try tryIsSuccess(nil) }) + XCTAssert(result2.error == error) + } + + func testMaterializeInferrence() { + let result = Result(attempt: { try tryIsSuccess(nil) }) + XCTAssert((type(of: result) as Any.Type) is Result.Type) + } + + // MARK: Recover + + func testRecoverProducesLeftForLeftSuccess() { + let left = Result.success("left") + XCTAssertEqual(left.recover("right"), "left") + } + + func testRecoverProducesRightForLeftFailure() { + let left = Result.failure(Error.a) + XCTAssertEqual(left.recover("right"), "right") + } + + // MARK: Recover With + + func testRecoverWithProducesLeftForLeftSuccess() { + let left = Result.success("left") + let right = Result.success("right") + + XCTAssertEqual(left.recover(with: right).value, "left") + } + + func testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess() { + struct Error: Swift.Error {} + + let left = Result.failure(Error()) + let right = Result.success("right") + + XCTAssertEqual(left.recover(with: right).value, "right") + } + + func testRecoverWithProducesRightFailureForLeftFailureAndRightFailure() { + enum Error: Swift.Error { case left, right } + + let left = Result.failure(.left) + let right = Result.failure(.right) + + XCTAssertEqual(left.recover(with: right).error, .right) + } + + func testTryMapProducesSuccess() { + let result = success.tryMap(tryIsSuccess) + XCTAssert(result == success) + } + + func testTryMapProducesFailure() { + let result = Result.success("fail").tryMap(tryIsSuccess) + XCTAssert(result == failure) + } +} + + +// MARK: - Fixtures + +enum Error: Swift.Error, LocalizedError { + case a, b + + var errorDescription: String? { + return "localized description" + } + + var failureReason: String? { + return "failure reason" + } + + var helpAnchor: String? { + return "help anchor" + } + + var recoverySuggestion: String? { + return "recovery suggestion" + } +} + +let success = Result.success("success") +let error = AnyError(Error.a) +let error2 = AnyError(Error.b) +let error3 = AnyError(NSError(domain: "Result", code: 42, userInfo: [NSLocalizedDescriptionKey: "localized description"])) +let failure = Result.failure(error) +let failure2 = Result.failure(error2) + +// MARK: - Helpers + +extension AnyError: Equatable { + public static func ==(lhs: AnyError, rhs: AnyError) -> Bool { + return lhs.error._code == rhs.error._code + && lhs.error._domain == rhs.error._domain + } +} + +func tryIsSuccess(_ text: String?) throws -> String { + guard let text = text, text == "success" else { + throw error + } + + return text +} + +extension NSError { + var function: String? { + return userInfo[Result<(), NSError>.functionKey] as? String + } + + var file: String? { + return userInfo[Result<(), NSError>.fileKey] as? String + } + + var line: Int? { + return userInfo[Result<(), NSError>.lineKey] as? Int + } +} + +import Foundation +import Result +import XCTest diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift new file mode 100644 index 0000000..7366acf --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift @@ -0,0 +1,57 @@ +import XCTest + +extension AnyErrorTests { + static let __allTests = [ + ("testAnyError", testAnyError), + ] +} + +extension NoErrorTests { + static let __allTests = [ + ("testEquatable", testEquatable), + ] +} + +extension ResultTests { + static let __allTests = [ + ("testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError", testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError), + ("testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError", testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError), + ("testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError", testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError), + ("testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError", testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError), + ("testBimapTransformsFailures", testBimapTransformsFailures), + ("testBimapTransformsSuccesses", testBimapTransformsSuccesses), + ("testErrorsIncludeTheCallingFunction", testErrorsIncludeTheCallingFunction), + ("testErrorsIncludeTheSourceFile", testErrorsIncludeTheSourceFile), + ("testErrorsIncludeTheSourceLine", testErrorsIncludeTheSourceLine), + ("testFanout", testFanout), + ("testInitOptionalFailure", testInitOptionalFailure), + ("testInitOptionalSuccess", testInitOptionalSuccess), + ("testMapRewrapsFailures", testMapRewrapsFailures), + ("testMapTransformsSuccesses", testMapTransformsSuccesses), + ("testMaterializeInferrence", testMaterializeInferrence), + ("testMaterializeProducesFailures", testMaterializeProducesFailures), + ("testMaterializeProducesSuccesses", testMaterializeProducesSuccesses), + ("testRecoverProducesLeftForLeftSuccess", testRecoverProducesLeftForLeftSuccess), + ("testRecoverProducesRightForLeftFailure", testRecoverProducesRightForLeftFailure), + ("testRecoverWithProducesLeftForLeftSuccess", testRecoverWithProducesLeftForLeftSuccess), + ("testRecoverWithProducesRightFailureForLeftFailureAndRightFailure", testRecoverWithProducesRightFailureForLeftFailureAndRightFailure), + ("testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess", testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess), + ("testTryCatchProducesFailures", testTryCatchProducesFailures), + ("testTryCatchProducesSuccesses", testTryCatchProducesSuccesses), + ("testTryCatchWithFunctionCatchProducesFailures", testTryCatchWithFunctionCatchProducesFailures), + ("testTryCatchWithFunctionProducesSuccesses", testTryCatchWithFunctionProducesSuccesses), + ("testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures", testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures), + ("testTryMapProducesFailure", testTryMapProducesFailure), + ("testTryMapProducesSuccess", testTryMapProducesSuccess), + ] +} + +#if !os(macOS) +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(AnyErrorTests.__allTests), + testCase(NoErrorTests.__allTests), + testCase(ResultTests.__allTests), + ] +} +#endif diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/.gitignore b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/.gitignore new file mode 100644 index 0000000..b29206a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/.gitignore @@ -0,0 +1 @@ +Carthage/Build diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig new file mode 100644 index 0000000..99b7fc8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig @@ -0,0 +1,179 @@ +// +// This file defines common settings that should be enabled for every new +// project. Typically, you want to use Debug, Release, or a similar variant +// instead. +// + +// Disable legacy-compatible header searching +ALWAYS_SEARCH_USER_PATHS = NO + +// Architectures to build +ARCHS = $(ARCHS_STANDARD) + +// Whether to warn when a floating-point value is used as a loop counter +CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES + +// Whether to warn about use of rand() and random() being used instead of arc4random() +CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES + +// Whether to warn about strcpy() and strcat() +CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES + +// Whether to enable module imports +CLANG_ENABLE_MODULES = YES + +// Enable ARC +CLANG_ENABLE_OBJC_ARC = YES + +// Warn about implicit conversions to boolean values that are suspicious. +// For example, writing 'if (foo)' with 'foo' being the name a function will trigger a warning. +CLANG_WARN_BOOL_CONVERSION = YES + +// Warn about implicit conversions of constant values that cause the constant value to change, +// either through a loss of precision, or entirely in its meaning. +CLANG_WARN_CONSTANT_CONVERSION = YES + +// Whether to warn when overriding deprecated methods +CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES + +// Warn about direct accesses to the Objective-C 'isa' pointer instead of using a runtime API. +CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR + +// Warn about declaring the same method more than once within the same @interface. +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES + +// Warn about loop bodies that are suspiciously empty. +CLANG_WARN_EMPTY_BODY = YES + +// Warn about implicit conversions between different kinds of enum values. +// For example, this can catch issues when using the wrong enum flag as an argument to a function or method. +CLANG_WARN_ENUM_CONVERSION = YES + +// Whether to warn on implicit conversions between signed/unsigned types +CLANG_WARN_IMPLICIT_SIGN_CONVERSION = NO + +// Warn about implicit conversions between pointers and integers. +// For example, this can catch issues when one incorrectly intermixes using NSNumbers and raw integers. +CLANG_WARN_INT_CONVERSION = YES + +// Don't warn about repeatedly using a weak reference without assigning the weak reference to a strong reference. Too many false positives. +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO + +// Warn about classes that unintentionally do not subclass a root class (such as NSObject). +CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR + +// Whether to warn on suspicious implicit conversions +CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES + +// Warn about potentially unreachable code +CLANG_WARN_UNREACHABLE_CODE = YES + +// The format of debugging symbols +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym + +// Whether to compile assertions in +ENABLE_NS_ASSERTIONS = YES + +// Whether to require objc_msgSend to be cast before invocation +ENABLE_STRICT_OBJC_MSGSEND = YES + +// Which C variant to use +GCC_C_LANGUAGE_STANDARD = gnu99 + +// Whether to enable exceptions for Objective-C +GCC_ENABLE_OBJC_EXCEPTIONS = YES + +// Whether to generate debugging symbols +GCC_GENERATE_DEBUGGING_SYMBOLS = YES + +// Whether to precompile the prefix header (if one is specified) +GCC_PRECOMPILE_PREFIX_HEADER = YES + +// Whether to enable strict aliasing, meaning that two pointers of different +// types (other than void * or any id type) cannot point to the same memory +// location +GCC_STRICT_ALIASING = YES + +// Whether symbols not explicitly exported are hidden by default (this primarily +// only affects C++ code) +GCC_SYMBOLS_PRIVATE_EXTERN = NO + +// Whether static variables are thread-safe by default +GCC_THREADSAFE_STATICS = NO + +// Which compiler to use +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 + +// Whether warnings are treated as errors +GCC_TREAT_WARNINGS_AS_ERRORS = YES + +// Whether to warn about 64-bit values being implicitly shortened to 32 bits +GCC_WARN_64_TO_32_BIT_CONVERSION = YES + +// Whether to warn about fields missing from structure initializers (only if +// designated initializers aren't used) +GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES + +// Whether to warn about missing function prototypes +GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO + +// Whether to warn about implicit conversions in the signedness of the type +// a pointer is pointing to (e.g., 'int *' getting converted to 'unsigned int *') +GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES + +// Whether to warn when the value returned from a function/method/block does not +// match its return type +GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR + +// Whether to warn on a class not implementing all the required methods of +// a protocol it declares conformance to +GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES + +// Whether to warn when switching on an enum value, and all possibilities are +// not accounted for +GCC_WARN_CHECK_SWITCH_STATEMENTS = YES + +// Whether to warn about the use of four-character constants +GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES + +// Whether to warn about an aggregate data type's initializer not being fully +// bracketed (e.g., array initializer syntax) +GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES + +// Whether to warn about missing braces or parentheses that make the meaning of +// the code ambiguous +GCC_WARN_MISSING_PARENTHESES = YES + +// Whether to warn about unsafe comparisons between values of different +// signedness +GCC_WARN_SIGN_COMPARE = YES + +// Whether to warn about the arguments to printf-style functions not matching +// the format specifiers +GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES + +// Warn if a "@selector(...)" expression referring to an undeclared selector is found +GCC_WARN_UNDECLARED_SELECTOR = YES + +// Warn if a variable might be clobbered by a setjmp call or if an automatic variable is used without prior initialization. +GCC_WARN_UNINITIALIZED_AUTOS = YES + +// Whether to warn about static functions that are unused +GCC_WARN_UNUSED_FUNCTION = YES + +// Whether to warn about labels that are unused +GCC_WARN_UNUSED_LABEL = YES + +// Whether to warn about variables that are never used +GCC_WARN_UNUSED_VARIABLE = YES + +// Whether to run the static analyzer with every build +RUN_CLANG_STATIC_ANALYZER = YES + +// Don't treat unknown warnings as errors, and disable GCC compatibility warnings and unused static const variable warnings +WARNING_CFLAGS = -Wno-error=unknown-warning-option -Wno-gcc-compat -Wno-unused-const-variable -Wno-nullability-completeness + +// This setting is on for new projects as of Xcode ~6.3, though it is still not +// the default. It warns if the same variable is declared in two binaries that +// are linked together. +GCC_NO_COMMON_BLOCKS = YES diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig new file mode 100644 index 0000000..6ef0040 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig @@ -0,0 +1,43 @@ +// +// This file defines the base configuration for a Debug build of any project. +// This should be set at the project level for the Debug configuration. +// + +#include "../Common.xcconfig" + +// Whether to strip debugging symbols when copying resources (like included +// binaries) +COPY_PHASE_STRIP = NO + +// The optimization level (0, 1, 2, 3, s) for the produced binary +GCC_OPTIMIZATION_LEVEL = 0 + +// Preproccessor definitions to apply to each file compiled +GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 + +// Whether to enable link-time optimizations (such as inlining across translation +// units) +LLVM_LTO = NO + +// Whether to only build the active architecture +ONLY_ACTIVE_ARCH = YES + +// Other compiler flags +// +// These settings catch some errors in integer arithmetic +OTHER_CFLAGS = -ftrapv + +// Other flags to pass to the Swift compiler +// +// This enables conditional compilation with #if DEBUG +OTHER_SWIFT_FLAGS = -D DEBUG + +// Whether to strip debugging symbols when copying the built product to its +// final installation location +STRIP_INSTALLED_PRODUCT = NO + +// The optimization level (-Onone, -O, -Ofast) for the produced Swift binary +SWIFT_OPTIMIZATION_LEVEL = -Onone + +// Disable Developer ID timestamping +OTHER_CODE_SIGN_FLAGS = --timestamp=none diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig new file mode 100644 index 0000000..0d01553 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig @@ -0,0 +1,27 @@ +// +// This file defines the base configuration for an optional profiling-specific +// build of any project. To use these settings, create a Profile configuration +// in your project, and use this file at the project level for the new +// configuration. +// + +// based on the Release configuration, with some stuff related to debugging +// symbols re-enabled +#include "Release.xcconfig" + +// Whether to strip debugging symbols when copying resources (like included +// binaries) +COPY_PHASE_STRIP = NO + +// Whether to only build the active architecture +ONLY_ACTIVE_ARCH = YES + +// Whether to strip debugging symbols when copying the built product to its +// final installation location +STRIP_INSTALLED_PRODUCT = NO + +// Whether to perform App Store validation checks +VALIDATE_PRODUCT = NO + +// Disable Developer ID timestamping +OTHER_CODE_SIGN_FLAGS = --timestamp=none diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig new file mode 100644 index 0000000..c83729b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig @@ -0,0 +1,34 @@ +// +// This file defines the base configuration for a Release build of any project. +// This should be set at the project level for the Release configuration. +// + +#include "../Common.xcconfig" + +// Whether to strip debugging symbols when copying resources (like included +// binaries) +COPY_PHASE_STRIP = YES + +// The optimization level (0, 1, 2, 3, s) for the produced binary +GCC_OPTIMIZATION_LEVEL = s + +// Preproccessor definitions to apply to each file compiled +GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 + +// Whether to enable link-time optimizations (such as inlining across translation +// units) +LLVM_LTO = NO + +// Whether to only build the active architecture +ONLY_ACTIVE_ARCH = NO + +// Whether to strip debugging symbols when copying the built product to its +// final installation location +STRIP_INSTALLED_PRODUCT = YES + +// The optimization level (-Onone, -O, -Owholemodule) for the produced Swift binary +SWIFT_OPTIMIZATION_LEVEL = -Owholemodule + +// Whether to perform App Store validation checks +VALIDATE_PRODUCT = YES + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig new file mode 100644 index 0000000..2da35e8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig @@ -0,0 +1,10 @@ +// +// This file defines the base configuration for a Test build of any project. +// This should be set at the project level for the Test configuration. +// + +#include "Debug.xcconfig" + +// Sandboxed apps can't be unit tested since they can't load some random +// external bundle. So we disable sandboxing for testing. +CODE_SIGN_ENTITLEMENTS = diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig new file mode 100644 index 0000000..a91feca --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig @@ -0,0 +1,12 @@ +// +// This file defines additional configuration options that are appropriate only +// for an application. Typically, you want to use a platform-specific variant +// instead. +// + +// Whether to strip out code that isn't called from anywhere +DEAD_CODE_STRIPPING = NO + +// Sets the @rpath for the application such that it can include frameworks in +// the application bundle (inside the "Frameworks" folder) +LD_RUNPATH_SEARCH_PATHS = @executable_path/../Frameworks @loader_path/../Frameworks @executable_path/Frameworks diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig new file mode 100644 index 0000000..24ae2e5 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig @@ -0,0 +1,32 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework. Typically, you want to use a platform-specific variant +// instead. +// + +// Whether to strip out code that isn't called from anywhere +DEAD_CODE_STRIPPING = NO + +// Whether this framework should define an LLVM module +DEFINES_MODULE = YES + +// Whether function calls should be position-dependent (should always be +// disabled for library code) +GCC_DYNAMIC_NO_PIC = NO + +// Default frameworks to the name of the project, instead of any +// platform-specific target +PRODUCT_NAME = $(PROJECT_NAME) + +// Enables the framework to be included from any location as long as the +// loader’s runpath search paths includes it. For example from an application +// bundle (inside the "Frameworks" folder) or shared folder +INSTALL_PATH = @rpath +LD_DYLIB_INSTALL_NAME = @rpath/$(PRODUCT_NAME).$(WRAPPER_EXTENSION)/$(PRODUCT_NAME) +SKIP_INSTALL = YES + +// Disallows use of APIs that are not available +// to app extensions and linking to frameworks +// that have not been built with this setting enabled. +APPLICATION_EXTENSION_API_ONLY = YES + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig new file mode 100644 index 0000000..b3b2b87 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig @@ -0,0 +1,32 @@ +// +// This file defines additional configuration options that are appropriate only +// for a static library. Typically, you want to use a platform-specific variant +// instead. +// + +// Whether to strip out code that isn't called from anywhere +DEAD_CODE_STRIPPING = NO + +// Whether to strip debugging symbols when copying resources (like included +// binaries). +// +// Overrides Release.xcconfig when used at the target level. +COPY_PHASE_STRIP = NO + +// Whether function calls should be position-dependent (should always be +// disabled for library code) +GCC_DYNAMIC_NO_PIC = NO + +// Copy headers to "include/LibraryName" in the build folder by default. This +// lets consumers use #import syntax even for static +// libraries +PUBLIC_HEADERS_FOLDER_PATH = include/$PRODUCT_NAME + +// Don't include in an xcarchive +SKIP_INSTALL = YES + +// Disallows use of APIs that are not available +// to app extensions and linking to frameworks +// that have not been built with this setting enabled. +APPLICATION_EXTENSION_API_ONLY = YES + diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig new file mode 100644 index 0000000..2e552c7 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig @@ -0,0 +1,15 @@ +// +// This file defines additional configuration options that are appropriate only +// for an application on Mac OS X. This should be set at the target level for +// each project configuration. +// + +// Import base application settings +#include "../Base/Targets/Application.xcconfig" + +// Apply common settings specific to Mac OS X +#include "Mac-Base.xcconfig" + +// Whether function calls should be position-dependent (should always be +// disabled for library code) +GCC_DYNAMIC_NO_PIC = YES diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig new file mode 100644 index 0000000..8fdeccc --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig @@ -0,0 +1,19 @@ +// +// This file defines additional configuration options that are appropriate only +// for Mac OS X. This file is not standalone -- it is meant to be included into +// a configuration file for a specific type of target. +// + +// Whether to combine multiple image resolutions into a multirepresentational +// TIFF +COMBINE_HIDPI_IMAGES = YES + +// Where to find embedded frameworks +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks + +// The base SDK to use (if no version is specified, the latest version is +// assumed) +SDKROOT = macosx + +// Supported build architectures +VALID_ARCHS = x86_64 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig new file mode 100644 index 0000000..1e2a37c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig @@ -0,0 +1,18 @@ +// +// This file defines additional configuration options that are appropriate only +// for a dynamic library on Mac OS X. This should be set at the target level +// for each project configuration. +// + +// Import common settings specific to Mac OS X +#include "Mac-Base.xcconfig" + +// Whether to strip out code that isn't called from anywhere +DEAD_CODE_STRIPPING = NO + +// Whether function calls should be position-dependent (should always be +// disabled for library code) +GCC_DYNAMIC_NO_PIC = NO + +// Don't include in an xcarchive +SKIP_INSTALL = YES diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig new file mode 100644 index 0000000..dd98764 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework on OS X. This should be set at the target level for each +// project configuration. +// + +// Import base framework settings +#include "../Base/Targets/Framework.xcconfig" + +// Import common settings specific to Mac OS X +#include "Mac-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig new file mode 100644 index 0000000..97d0318 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a static library on Mac OS X. This should be set at the target level for +// each project configuration. +// + +// Import base static library settings +#include "../Base/Targets/StaticLibrary.xcconfig" + +// Apply common settings specific to Mac OS X +#include "Mac-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/README.md b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/README.md new file mode 100644 index 0000000..8b69024 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/README.md @@ -0,0 +1,13 @@ +This project intends to aggregate common or universal Xcode configuration settings, keeping them in hierarchial Xcode configuration files for easy modification and reuse. + +## License + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to [unlicense.org](http://unlicense.org). diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig new file mode 100644 index 0000000..a700868 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for an application on iOS. This should be set at the target level for each +// project configuration. +// + +// Import base application settings +#include "../Base/Targets/Application.xcconfig" + +// Apply common settings specific to iOS +#include "iOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig new file mode 100644 index 0000000..f45f905 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig @@ -0,0 +1,18 @@ +// +// This file defines additional configuration options that are appropriate only +// for iOS. This file is not standalone -- it is meant to be included into +// a configuration file for a specific type of target. +// + +// Xcode needs this to find archived headers if SKIP_INSTALL is set +HEADER_SEARCH_PATHS = $(OBJROOT)/UninstalledProducts/include + +// Where to find embedded frameworks +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks + +// The base SDK to use (if no version is specified, the latest version is +// assumed) +SDKROOT = iphoneos + +// Supported device families (1 is iPhone, 2 is iPad) +TARGETED_DEVICE_FAMILY = 1,2 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig new file mode 100644 index 0000000..e538a7d --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework on iOS. This should be set at the target level for each +// project configuration. +// + +// Import base framework settings +#include "../Base/Targets/Framework.xcconfig" + +// Import common settings specific to iOS +#include "iOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..7e3b507 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a static library on iOS. This should be set at the target level for each +// project configuration. +// + +// Import base static library settings +#include "../Base/Targets/StaticLibrary.xcconfig" + +// Apply common settings specific to iOS +#include "iOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig new file mode 100644 index 0000000..2998e2b --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for an application on watchOS. This should be set at the target level for +// each project configuration. +// + +// Import base application settings +#include "../Base/Targets/Application.xcconfig" + +// Apply common settings specific to watchOS +#include "tvOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig new file mode 100644 index 0000000..05f72cd --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig @@ -0,0 +1,15 @@ +// +// This file defines additional configuration options that are appropriate only +// for watchOS. This file is not standalone -- it is meant to be included into +// a configuration file for a specific type of target. +// + +// Where to find embedded frameworks +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks + +// The base SDK to use (if no version is specified, the latest version is +// assumed) +SDKROOT = appletvos + +// Supported device families +TARGETED_DEVICE_FAMILY = 3 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig new file mode 100644 index 0000000..69a23e8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework on watchOS. This should be set at the target level for each +// project configuration. +// + +// Import base framework settings +#include "../Base/Targets/Framework.xcconfig" + +// Import common settings specific to iOS +#include "tvOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..0efb4c4 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a static library on watchOS. This should be set at the target level for +// each project configuration. +// + +// Import base static library settings +#include "../Base/Targets/StaticLibrary.xcconfig" + +// Apply common settings specific to watchOS +#include "tvOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig new file mode 100644 index 0000000..5d88df9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for an application on watchOS. This should be set at the target level for +// each project configuration. +// + +// Import base application settings +#include "../Base/Targets/Application.xcconfig" + +// Apply common settings specific to watchOS +#include "watchOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig new file mode 100644 index 0000000..21e4a82 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig @@ -0,0 +1,15 @@ +// +// This file defines additional configuration options that are appropriate only +// for watchOS. This file is not standalone -- it is meant to be included into +// a configuration file for a specific type of target. +// + +// Where to find embedded frameworks +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks + +// The base SDK to use (if no version is specified, the latest version is +// assumed) +SDKROOT = watchos + +// Supported device families +TARGETED_DEVICE_FAMILY = 4 diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig new file mode 100644 index 0000000..3893494 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework on watchOS. This should be set at the target level for each +// project configuration. +// + +// Import base framework settings +#include "../Base/Targets/Framework.xcconfig" + +// Import common settings specific to iOS +#include "watchOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..b9f92d8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig @@ -0,0 +1,11 @@ +// +// This file defines additional configuration options that are appropriate only +// for a static library on watchOS. This should be set at the target level for +// each project configuration. +// + +// Import base static library settings +#include "../Base/Targets/StaticLibrary.xcconfig" + +// Apply common settings specific to watchOS +#include "watchOS-Base.xcconfig" diff --git a/Carthage/Checkouts/Commandant/Commandant.podspec b/Carthage/Checkouts/Commandant/Commandant.podspec new file mode 100644 index 0000000..cb75c85 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.podspec @@ -0,0 +1,32 @@ +# +# Commandant.podspec +# Commandant +# + +# Be sure to run `pod spec lint Commandant.podspec' to ensure this spec is valid before committing. +# +# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html + +Pod::Spec.new do |s| + s.name = "Commandant" + s.version = "0.15.0" + s.summary = "Type-safe command line argument handling" + s.description = <<-DESC +Commandant is a Swift framework for parsing command-line arguments, inspired by Argo +(which is, in turn, inspired by the Haskell library Aeson). + DESC + + s.homepage = "https://github.com/Carthage/Commandant" + s.license = { type: "MIT", file: "LICENSE.md" } + s.authors = { "Carthage contributors" => "https://github.com/Carthage/Commandant/graphs/contributors" } + + s.platform = :osx, "10.9" + s.source = { git: "https://github.com/Carthage/Commandant.git", tag: s.version } + + s.source_files = "Sources/**/*.swift" + + s.dependency "Result", "~> 4.0" + + s.cocoapods_version = ">= 1.4.0" + s.swift_version = "4.0" +end diff --git a/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.pbxproj b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.pbxproj new file mode 100644 index 0000000..072ede3 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.pbxproj @@ -0,0 +1,644 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 680759651FC5A25D00D6CA70 /* OptionsWithEnumProtocolSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680759631FC5A1F600D6CA70 /* OptionsWithEnumProtocolSpec.swift */; }; + CD2ED3411C1E6C5D0076092B /* Argument.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2ED3401C1E6C5D0076092B /* Argument.swift */; }; + CD2ED3431C1E6D540076092B /* ArgumentProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2ED3421C1E6D540076092B /* ArgumentProtocol.swift */; }; + CDCE78341FBAB047005A9F76 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE78331FBAB047005A9F76 /* OrderedSet.swift */; }; + CDCE78361FBAB0A2005A9F76 /* OrderedSetSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE78351FBAB0A2005A9F76 /* OrderedSetSpec.swift */; }; + CDFC88361C3C0612003AC8F8 /* CommandSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFC88351C3C0612003AC8F8 /* CommandSpec.swift */; }; + D00CCDDF1A20717400109F8C /* Commandant.h in Headers */ = {isa = PBXBuildFile; fileRef = D00CCDDE1A20717400109F8C /* Commandant.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D00CCDE51A20717400109F8C /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00CCDD91A20717400109F8C /* Commandant.framework */; }; + D00CCE241A2073DA00109F8C /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00CCE221A2073DA00109F8C /* Nimble.framework */; }; + D00CCE251A2073DA00109F8C /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00CCE231A2073DA00109F8C /* Quick.framework */; }; + D00CCE271A20741300109F8C /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CCE261A20741300109F8C /* Command.swift */; }; + D00CCE291A20741C00109F8C /* OptionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CCE281A20741C00109F8C /* OptionSpec.swift */; }; + D00CCE2B1A20748500109F8C /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CCE2A1A20748500109F8C /* Errors.swift */; }; + D00CCE2D1A2075ED00109F8C /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CCE2C1A2075ED00109F8C /* ArgumentParser.swift */; }; + D00CCE2F1A2075F700109F8C /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CCE2E1A2075F700109F8C /* Option.swift */; }; + D021309A1AF87D6E00B9EC20 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D02130981AF87D6E00B9EC20 /* Result.framework */; }; + D0BF14FB1A4C8957003147BC /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BF14FA1A4C8957003147BC /* HelpCommand.swift */; }; + D8169D871ACB942D00923FB0 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8169D861ACB942D00923FB0 /* Switch.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D00CCDE61A20717400109F8C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D00CCDD01A20717400109F8C /* Project object */; + proxyType = 1; + remoteGlobalIDString = D00CCDD81A20717400109F8C; + remoteInfo = Commandant; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 680759631FC5A1F600D6CA70 /* OptionsWithEnumProtocolSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionsWithEnumProtocolSpec.swift; sourceTree = ""; }; + 6CAD549C1D371A4E00A2D031 /* LinuxMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = Tests/LinuxMain.swift; sourceTree = SOURCE_ROOT; }; + CD2ED3401C1E6C5D0076092B /* Argument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Argument.swift; sourceTree = ""; }; + CD2ED3421C1E6D540076092B /* ArgumentProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentProtocol.swift; sourceTree = ""; }; + CDCE78331FBAB047005A9F76 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = ""; }; + CDCE78351FBAB0A2005A9F76 /* OrderedSetSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSetSpec.swift; sourceTree = ""; }; + CDFC88351C3C0612003AC8F8 /* CommandSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandSpec.swift; sourceTree = ""; }; + D00CCDD91A20717400109F8C /* Commandant.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Commandant.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D00CCDDD1A20717400109F8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D00CCDDE1A20717400109F8C /* Commandant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Commandant.h; sourceTree = ""; }; + D00CCDE41A20717400109F8C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D00CCDEA1A20717400109F8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D00CCDF81A20719500109F8C /* Common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Common.xcconfig; sourceTree = ""; }; + D00CCDFA1A20719500109F8C /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D00CCDFB1A20719500109F8C /* Profile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Profile.xcconfig; sourceTree = ""; }; + D00CCDFC1A20719500109F8C /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + D00CCDFD1A20719500109F8C /* Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Test.xcconfig; sourceTree = ""; }; + D00CCDFF1A20719500109F8C /* Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Application.xcconfig; sourceTree = ""; }; + D00CCE001A20719500109F8C /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = ""; }; + D00CCE011A20719500109F8C /* StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = StaticLibrary.xcconfig; sourceTree = ""; }; + D00CCE031A20719500109F8C /* iOS-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Application.xcconfig"; sourceTree = ""; }; + D00CCE041A20719500109F8C /* iOS-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Base.xcconfig"; sourceTree = ""; }; + D00CCE051A20719500109F8C /* iOS-Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Framework.xcconfig"; sourceTree = ""; }; + D00CCE061A20719500109F8C /* iOS-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-StaticLibrary.xcconfig"; sourceTree = ""; }; + D00CCE081A20719500109F8C /* Mac-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Application.xcconfig"; sourceTree = ""; }; + D00CCE091A20719500109F8C /* Mac-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Base.xcconfig"; sourceTree = ""; }; + D00CCE0A1A20719500109F8C /* Mac-DynamicLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-DynamicLibrary.xcconfig"; sourceTree = ""; }; + D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Framework.xcconfig"; sourceTree = ""; }; + D00CCE0C1A20719500109F8C /* Mac-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-StaticLibrary.xcconfig"; sourceTree = ""; }; + D00CCE0D1A20719500109F8C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + D00CCE221A2073DA00109F8C /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D00CCE231A2073DA00109F8C /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D00CCE261A20741300109F8C /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = ""; }; + D00CCE281A20741C00109F8C /* OptionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionSpec.swift; sourceTree = ""; }; + D00CCE2A1A20748500109F8C /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + D00CCE2C1A2075ED00109F8C /* ArgumentParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentParser.swift; sourceTree = ""; }; + D00CCE2E1A2075F700109F8C /* Option.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Option.swift; sourceTree = ""; }; + D02130981AF87D6E00B9EC20 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D0BF14FA1A4C8957003147BC /* HelpCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelpCommand.swift; sourceTree = ""; }; + D8169D861ACB942D00923FB0 /* Switch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D00CCDD51A20717400109F8C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D021309A1AF87D6E00B9EC20 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D00CCDE11A20717400109F8C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D00CCE251A2073DA00109F8C /* Quick.framework in Frameworks */, + D00CCE241A2073DA00109F8C /* Nimble.framework in Frameworks */, + D00CCDE51A20717400109F8C /* Commandant.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D00CCDCF1A20717400109F8C = { + isa = PBXGroup; + children = ( + D00CCDDB1A20717400109F8C /* Commandant */, + D00CCDE81A20717400109F8C /* Tests */, + D00CCDF61A20719500109F8C /* Configuration */, + D00CCDDA1A20717400109F8C /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D00CCDDA1A20717400109F8C /* Products */ = { + isa = PBXGroup; + children = ( + D00CCDD91A20717400109F8C /* Commandant.framework */, + D00CCDE41A20717400109F8C /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D00CCDDB1A20717400109F8C /* Commandant */ = { + isa = PBXGroup; + children = ( + D00CCDDE1A20717400109F8C /* Commandant.h */, + D0BF14F81A4C892E003147BC /* Core */, + D0BF14F91A4C893B003147BC /* Built-in Commands */, + D00CCDDC1A20717400109F8C /* Supporting Files */, + ); + name = Commandant; + path = Sources/Commandant; + sourceTree = ""; + }; + D00CCDDC1A20717400109F8C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D02130981AF87D6E00B9EC20 /* Result.framework */, + D00CCDDD1A20717400109F8C /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D00CCDE81A20717400109F8C /* Tests */ = { + isa = PBXGroup; + children = ( + CDFC88351C3C0612003AC8F8 /* CommandSpec.swift */, + D00CCE281A20741C00109F8C /* OptionSpec.swift */, + 680759631FC5A1F600D6CA70 /* OptionsWithEnumProtocolSpec.swift */, + CDCE78351FBAB0A2005A9F76 /* OrderedSetSpec.swift */, + D00CCDE91A20717400109F8C /* Supporting Files */, + 6CAD549C1D371A4E00A2D031 /* LinuxMain.swift */, + ); + name = Tests; + path = Tests/CommandantTests; + sourceTree = ""; + }; + D00CCDE91A20717400109F8C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D00CCE221A2073DA00109F8C /* Nimble.framework */, + D00CCE231A2073DA00109F8C /* Quick.framework */, + D00CCDEA1A20717400109F8C /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D00CCDF61A20719500109F8C /* Configuration */ = { + isa = PBXGroup; + children = ( + D00CCDF71A20719500109F8C /* Base */, + D00CCE021A20719500109F8C /* iOS */, + D00CCE071A20719500109F8C /* Mac OS X */, + D00CCE0D1A20719500109F8C /* README.md */, + ); + name = Configuration; + path = Carthage/Checkouts/xcconfigs; + sourceTree = ""; + }; + D00CCDF71A20719500109F8C /* Base */ = { + isa = PBXGroup; + children = ( + D00CCDF81A20719500109F8C /* Common.xcconfig */, + D00CCDF91A20719500109F8C /* Configurations */, + D00CCDFE1A20719500109F8C /* Targets */, + ); + path = Base; + sourceTree = ""; + }; + D00CCDF91A20719500109F8C /* Configurations */ = { + isa = PBXGroup; + children = ( + D00CCDFA1A20719500109F8C /* Debug.xcconfig */, + D00CCDFB1A20719500109F8C /* Profile.xcconfig */, + D00CCDFC1A20719500109F8C /* Release.xcconfig */, + D00CCDFD1A20719500109F8C /* Test.xcconfig */, + ); + path = Configurations; + sourceTree = ""; + }; + D00CCDFE1A20719500109F8C /* Targets */ = { + isa = PBXGroup; + children = ( + D00CCDFF1A20719500109F8C /* Application.xcconfig */, + D00CCE001A20719500109F8C /* Framework.xcconfig */, + D00CCE011A20719500109F8C /* StaticLibrary.xcconfig */, + ); + path = Targets; + sourceTree = ""; + }; + D00CCE021A20719500109F8C /* iOS */ = { + isa = PBXGroup; + children = ( + D00CCE031A20719500109F8C /* iOS-Application.xcconfig */, + D00CCE041A20719500109F8C /* iOS-Base.xcconfig */, + D00CCE051A20719500109F8C /* iOS-Framework.xcconfig */, + D00CCE061A20719500109F8C /* iOS-StaticLibrary.xcconfig */, + ); + path = iOS; + sourceTree = ""; + }; + D00CCE071A20719500109F8C /* Mac OS X */ = { + isa = PBXGroup; + children = ( + D00CCE081A20719500109F8C /* Mac-Application.xcconfig */, + D00CCE091A20719500109F8C /* Mac-Base.xcconfig */, + D00CCE0A1A20719500109F8C /* Mac-DynamicLibrary.xcconfig */, + D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */, + D00CCE0C1A20719500109F8C /* Mac-StaticLibrary.xcconfig */, + ); + path = "Mac OS X"; + sourceTree = ""; + }; + D0BF14F81A4C892E003147BC /* Core */ = { + isa = PBXGroup; + children = ( + CD2ED3401C1E6C5D0076092B /* Argument.swift */, + D00CCE2C1A2075ED00109F8C /* ArgumentParser.swift */, + CD2ED3421C1E6D540076092B /* ArgumentProtocol.swift */, + D00CCE261A20741300109F8C /* Command.swift */, + D00CCE2A1A20748500109F8C /* Errors.swift */, + D00CCE2E1A2075F700109F8C /* Option.swift */, + CDCE78331FBAB047005A9F76 /* OrderedSet.swift */, + D8169D861ACB942D00923FB0 /* Switch.swift */, + ); + name = Core; + sourceTree = ""; + }; + D0BF14F91A4C893B003147BC /* Built-in Commands */ = { + isa = PBXGroup; + children = ( + D0BF14FA1A4C8957003147BC /* HelpCommand.swift */, + ); + name = "Built-in Commands"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D00CCDD61A20717400109F8C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D00CCDDF1A20717400109F8C /* Commandant.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D00CCDD81A20717400109F8C /* Commandant */ = { + isa = PBXNativeTarget; + buildConfigurationList = D00CCDEF1A20717400109F8C /* Build configuration list for PBXNativeTarget "Commandant" */; + buildPhases = ( + D00CCDD41A20717400109F8C /* Sources */, + D00CCDD51A20717400109F8C /* Frameworks */, + D00CCDD61A20717400109F8C /* Headers */, + D00CCDD71A20717400109F8C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Commandant; + productName = Commandant; + productReference = D00CCDD91A20717400109F8C /* Commandant.framework */; + productType = "com.apple.product-type.framework"; + }; + D00CCDE31A20717400109F8C /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D00CCDF21A20717400109F8C /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + D00CCDE01A20717400109F8C /* Sources */, + D00CCDE11A20717400109F8C /* Frameworks */, + D00CCDE21A20717400109F8C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D00CCDE71A20717400109F8C /* PBXTargetDependency */, + ); + name = Tests; + productName = Tests; + productReference = D00CCDE41A20717400109F8C /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D00CCDD01A20717400109F8C /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftMigration = 0700; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = Carthage; + TargetAttributes = { + D00CCDD81A20717400109F8C = { + CreatedOnToolsVersion = 6.1.1; + LastSwiftMigration = 0800; + }; + D00CCDE31A20717400109F8C = { + CreatedOnToolsVersion = 6.1.1; + LastSwiftMigration = 0800; + }; + }; + }; + buildConfigurationList = D00CCDD31A20717400109F8C /* Build configuration list for PBXProject "Commandant" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D00CCDCF1A20717400109F8C; + productRefGroup = D00CCDDA1A20717400109F8C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D00CCDD81A20717400109F8C /* Commandant */, + D00CCDE31A20717400109F8C /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D00CCDD71A20717400109F8C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D00CCDE21A20717400109F8C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D00CCDD41A20717400109F8C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDCE78341FBAB047005A9F76 /* OrderedSet.swift in Sources */, + CD2ED3411C1E6C5D0076092B /* Argument.swift in Sources */, + D0BF14FB1A4C8957003147BC /* HelpCommand.swift in Sources */, + CD2ED3431C1E6D540076092B /* ArgumentProtocol.swift in Sources */, + D00CCE2F1A2075F700109F8C /* Option.swift in Sources */, + D00CCE2B1A20748500109F8C /* Errors.swift in Sources */, + D8169D871ACB942D00923FB0 /* Switch.swift in Sources */, + D00CCE271A20741300109F8C /* Command.swift in Sources */, + D00CCE2D1A2075ED00109F8C /* ArgumentParser.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D00CCDE01A20717400109F8C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFC88361C3C0612003AC8F8 /* CommandSpec.swift in Sources */, + D00CCE291A20741C00109F8C /* OptionSpec.swift in Sources */, + 680759651FC5A25D00D6CA70 /* OptionsWithEnumProtocolSpec.swift in Sources */, + CDCE78361FBAB0A2005A9F76 /* OrderedSetSpec.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D00CCDE71A20717400109F8C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D00CCDD81A20717400109F8C /* Commandant */; + targetProxy = D00CCDE61A20717400109F8C /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + D00CCDED1A20717400109F8C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCDFA1A20719500109F8C /* Debug.xcconfig */; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_TESTABILITY = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D00CCDEE1A20717400109F8C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCDFC1A20719500109F8C /* Release.xcconfig */; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CURRENT_PROJECT_VERSION = 1; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D00CCDF01A20717400109F8C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Commandant/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + D00CCDF11A20717400109F8C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Commandant/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D00CCDF31A20717400109F8C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE081A20719500109F8C /* Mac-Application.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/CommandantTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D00CCDF41A20717400109F8C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE081A20719500109F8C /* Mac-Application.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/CommandantTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D00CCE111A2072AB00109F8C /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCDFB1A20719500109F8C /* Profile.xcconfig */; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CURRENT_PROJECT_VERSION = 1; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Profile; + }; + D00CCE121A2072AB00109F8C /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Commandant/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + D00CCE131A2072AB00109F8C /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE081A20719500109F8C /* Mac-Application.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/CommandantTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + D00CCE141A2072BD00109F8C /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCDFD1A20719500109F8C /* Test.xcconfig */; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CURRENT_PROJECT_VERSION = 1; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Test; + }; + D00CCE151A2072BD00109F8C /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE0B1A20719500109F8C /* Mac-Framework.xcconfig */; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Commandant/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Test; + }; + D00CCE161A2072BD00109F8C /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D00CCE081A20719500109F8C /* Mac-Application.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/CommandantTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "org.carthage.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Test; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D00CCDD31A20717400109F8C /* Build configuration list for PBXProject "Commandant" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D00CCDED1A20717400109F8C /* Debug */, + D00CCE141A2072BD00109F8C /* Test */, + D00CCDEE1A20717400109F8C /* Release */, + D00CCE111A2072AB00109F8C /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D00CCDEF1A20717400109F8C /* Build configuration list for PBXNativeTarget "Commandant" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D00CCDF01A20717400109F8C /* Debug */, + D00CCE151A2072BD00109F8C /* Test */, + D00CCDF11A20717400109F8C /* Release */, + D00CCE121A2072AB00109F8C /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D00CCDF21A20717400109F8C /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D00CCDF31A20717400109F8C /* Debug */, + D00CCE161A2072BD00109F8C /* Test */, + D00CCDF41A20717400109F8C /* Release */, + D00CCE131A2072AB00109F8C /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D00CCDD01A20717400109F8C /* Project object */; +} diff --git a/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..20b6cf6 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Commandant/Commandant.xcodeproj/xcshareddata/xcschemes/Commandant.xcscheme b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/xcshareddata/xcschemes/Commandant.xcscheme new file mode 100644 index 0000000..ec5f507 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.xcodeproj/xcshareddata/xcschemes/Commandant.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Commandant.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Commandant/Commandant.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1582c71 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/Carthage/Checkouts/Commandant/Commandant.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Commandant/Commandant.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Commandant.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Commandant/LICENSE.md b/Carthage/Checkouts/Commandant/LICENSE.md new file mode 100644 index 0000000..d624889 --- /dev/null +++ b/Carthage/Checkouts/Commandant/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Carthage contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Carthage/Checkouts/Commandant/Package.resolved b/Carthage/Checkouts/Commandant/Package.resolved new file mode 100644 index 0000000..7a64a85 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Package.resolved @@ -0,0 +1,34 @@ +{ + "object": { + "pins": [ + { + "package": "Nimble", + "repositoryURL": "https://github.com/Quick/Nimble.git", + "state": { + "branch": null, + "revision": "8023e3980d91b470ad073d6da843b73f2eeb1844", + "version": "7.1.2" + } + }, + { + "package": "Quick", + "repositoryURL": "https://github.com/Quick/Quick.git", + "state": { + "branch": null, + "revision": "3e3023569c8d4c4a0d000f58db765df53041117f", + "version": "1.3.0" + } + }, + { + "package": "Result", + "repositoryURL": "https://github.com/antitypical/Result.git", + "state": { + "branch": null, + "revision": "8fc088dcf72802801efeecba76ea8fb041fb773d", + "version": "4.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/Carthage/Checkouts/Commandant/Package.swift b/Carthage/Checkouts/Commandant/Package.swift new file mode 100644 index 0000000..b918602 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Commandant", + products: [ + .library(name: "Commandant", targets: ["Commandant"]), + ], + dependencies: [ + .package(url: "https://github.com/antitypical/Result.git", from: "4.0.0"), + .package(url: "https://github.com/Quick/Quick.git", from: "1.3.0"), + .package(url: "https://github.com/Quick/Nimble.git", from: "7.1.2"), + ], + targets: [ + .target(name: "Commandant", dependencies: ["Result"]), + .testTarget(name: "CommandantTests", dependencies: ["Commandant", "Quick", "Nimble"]), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Commandant/README.md b/Carthage/Checkouts/Commandant/README.md new file mode 100644 index 0000000..5366a16 --- /dev/null +++ b/Carthage/Checkouts/Commandant/README.md @@ -0,0 +1,75 @@ +# Commandant + +Commandant is a Swift framework for parsing command-line arguments, inspired by [Argo](https://github.com/thoughtbot/Argo) (which is, in turn, inspired by the Haskell library [Aeson](http://hackage.haskell.org/package/aeson)). + +## Example + +With Commandant, a command and its associated options could be defined as follows: + +```swift +struct LogCommand: CommandProtocol { + typealias Options = LogOptions + + let verb = "log" + let function = "Reads the log" + + func run(_ options: Options) -> Result<(), YourErrorType> { + // Use the parsed options to do something interesting here. + return () + } +} + +struct LogOptions: OptionsProtocol { + let lines: Int + let verbose: Bool + let logName: String + + static func create(_ lines: Int) -> (Bool) -> (String) -> LogOptions { + return { verbose in { logName in LogOptions(lines: lines, verbose: verbose, logName: logName) } } + } + + static func evaluate(_ m: CommandMode) -> Result> { + return create + <*> m <| Option(key: "lines", defaultValue: 0, usage: "the number of lines to read from the logs") + <*> m <| Option(key: "verbose", defaultValue: false, usage: "show verbose output") + <*> m <| Argument(usage: "the log to read") + } +} +``` + +Then, each available command should be added to a registry: + +```swift +let commands = CommandRegistry() +commands.register(LogCommand()) +commands.register(VersionCommand()) +``` + +After which, arguments can be parsed by simply invoking the registry: + +```swift +var arguments = CommandLine.arguments + +// Remove the executable name. +assert(!arguments.isEmpty) +arguments.remove(at: 0) + +if let verb = arguments.first { + // Remove the command name. + arguments.remove(at: 0) + + if let result = commands.run(command: verb, arguments: arguments) { + // Handle success or failure. + } else { + // Unrecognized command. + } +} else { + // No command given. +} +``` + +For real-world examples, see the implementation of the [Carthage](https://github.com/Carthage/Carthage) command-line tool. + +## License + +Commandant is released under the [MIT license](LICENSE.md). diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Argument.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/Argument.swift new file mode 100644 index 0000000..cd7ff65 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Argument.swift @@ -0,0 +1,122 @@ +// +// Argument.swift +// Commandant +// +// Created by Syo Ikeda on 12/14/15. +// Copyright (c) 2015 Carthage. All rights reserved. +// + +import Result + +/// Describes an argument that can be provided on the command line. +public struct Argument { + /// The default value for this argument. This is the value that will be used + /// if the argument is never explicitly specified on the command line. + /// + /// If this is nil, this argument is always required. + public let defaultValue: T? + + /// A human-readable string describing the purpose of this argument. This will + /// be shown in help messages. + public let usage: String + + /// A human-readable string that describes this argument as a paramater shown + /// in the list of possible parameters in help messages (e.g. for "paths", the + /// user would see ). + public let usageParameter: String? + + public init(defaultValue: T? = nil, usage: String, usageParameter: String? = nil) { + self.defaultValue = defaultValue + self.usage = usage + self.usageParameter = usageParameter + } + + fileprivate func invalidUsageError(_ value: String) -> CommandantError { + let description = "Invalid value for '\(self.usageParameterDescription)': \(value)" + return .usageError(description: description) + } +} + +extension Argument { + /// A string describing this argument as a parameter in help messages. This falls back + /// to `"\(self)"` if `usageParameter` is `nil` + internal var usageParameterDescription: String { + return self.usageParameter.map { "<\($0)>" } ?? "\(self)" + } +} + +extension Argument where T: Sequence { + /// A string describing this argument as a parameter in help messages. This falls back + /// to `"\(self)"` if `usageParameter` is `nil` + internal var usageParameterDescription: String { + return self.usageParameter.map { "<\($0)…>" } ?? "\(self)" + } +} + +// MARK: - Operators + +extension CommandMode { + /// Evaluates the given argument in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the argument's `defaultValue` is used. + public static func <| (mode: CommandMode, argument: Argument) -> Result> { + switch mode { + case let .arguments(arguments): + guard let stringValue = arguments.consumePositionalArgument() else { + if let defaultValue = argument.defaultValue { + return .success(defaultValue) + } else { + return .failure(missingArgumentError(argument.usage)) + } + } + + if let value = T.from(string: stringValue) { + return .success(value) + } else { + return .failure(argument.invalidUsageError(stringValue)) + } + + case .usage: + return .failure(informativeUsageError(argument)) + } + } + + /// Evaluates the given argument list in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the argument's `defaultValue` is used. + public static func <| (mode: CommandMode, argument: Argument<[T]>) -> Result<[T], CommandantError> { + switch mode { + case let .arguments(arguments): + guard let firstValue = arguments.consumePositionalArgument() else { + if let defaultValue = argument.defaultValue { + return .success(defaultValue) + } else { + return .failure(missingArgumentError(argument.usage)) + } + } + + var values = [T]() + + guard let value = T.from(string: firstValue) else { + return .failure(argument.invalidUsageError(firstValue)) + } + + values.append(value) + + while let nextValue = arguments.consumePositionalArgument() { + guard let value = T.from(string: nextValue) else { + return .failure(argument.invalidUsageError(nextValue)) + } + + values.append(value) + } + + return .success(values) + + case .usage: + return .failure(informativeUsageError(argument)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentParser.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentParser.swift new file mode 100644 index 0000000..3ca9c21 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentParser.swift @@ -0,0 +1,194 @@ +// +// ArgumentParser.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-11-21. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +import Foundation +import Result + +/// Represents an argument passed on the command line. +private enum RawArgument: Equatable { + /// A key corresponding to an option (e.g., `verbose` for `--verbose`). + case key(String) + + /// A value, either associated with an option or passed as a positional + /// argument. + case value(String) + + /// One or more flag arguments (e.g 'r' and 'f' for `-rf`) + case flag(OrderedSet) +} + +#if !swift(>=4.1) +private func ==(lhs: RawArgument, rhs: RawArgument) -> Bool { + switch (lhs, rhs) { + case let (.key(left), .key(right)): + return left == right + + case let (.value(left), .value(right)): + return left == right + + case let (.flag(left), .flag(right)): + return left == right + + default: + return false + } +} +#endif + +extension RawArgument: CustomStringConvertible { + fileprivate var description: String { + switch self { + case let .key(key): + return "--\(key)" + + case let .value(value): + return "\"\(value)\"" + + case let .flag(flags): + return "-\(String(flags))" + } + } +} + +/// Destructively parses a list of command-line arguments. +public final class ArgumentParser { + /// The remaining arguments to be extracted, in their raw form. + private var rawArguments: [RawArgument] = [] + + /// Initializes the generator from a simple list of command-line arguments. + public init(_ arguments: [String]) { + // The first instance of `--` terminates the option list. + let params = arguments.split(maxSplits: 1, omittingEmptySubsequences: false) { $0 == "--" } + + // Parse out the keyed and flag options. + let options = params.first! + rawArguments.append(contentsOf: options.map { arg in + if arg.hasPrefix("-") { + // Do we have `--{key}` or `-{flags}`. + let opt = arg.dropFirst() + if opt.first == "-" { + return .key(String(opt.dropFirst())) + } else { + return .flag(OrderedSet(opt)) + } + } else { + return .value(arg) + } + }) + + // Remaining arguments are all positional parameters. + if params.count == 2 { + let positional = params.last! + rawArguments.append(contentsOf: positional.map(RawArgument.value)) + } + } + + /// Returns the remaining arguments. + internal var remainingArguments: [String]? { + return rawArguments.isEmpty ? nil : rawArguments.map { $0.description } + } + + /// Returns whether the given key was enabled or disabled, or nil if it + /// was not given at all. + /// + /// If the key is found, it is then removed from the list of arguments + /// remaining to be parsed. + internal func consumeBoolean(forKey key: String) -> Bool? { + let oldArguments = rawArguments + rawArguments.removeAll() + + var result: Bool? + for arg in oldArguments { + if arg == .key(key) { + result = true + } else if arg == .key("no-\(key)") { + result = false + } else { + rawArguments.append(arg) + } + } + + return result + } + + /// Returns the value associated with the given flag, or nil if the flag was + /// not specified. If the key is presented, but no value was given, an error + /// is returned. + /// + /// If a value is found, the key and the value are both removed from the + /// list of arguments remaining to be parsed. + internal func consumeValue(forKey key: String) -> Result> { + let oldArguments = rawArguments + rawArguments.removeAll() + + var foundValue: String? + var index = 0 + + while index < oldArguments.count { + defer { index += 1 } + let arg = oldArguments[index] + + guard arg == .key(key) else { + rawArguments.append(arg) + continue + } + + index += 1 + guard index < oldArguments.count, case let .value(value) = oldArguments[index] else { + return .failure(missingArgumentError("--\(key)")) + } + + foundValue = value + } + + return .success(foundValue) + } + + /// Returns the next positional argument that hasn't yet been returned, or + /// nil if there are no more positional arguments. + internal func consumePositionalArgument() -> String? { + for (index, arg) in rawArguments.enumerated() { + if case let .value(value) = arg { + rawArguments.remove(at: index) + return value + } + } + + return nil + } + + /// Returns whether the given key was specified and removes it from the + /// list of arguments remaining. + internal func consume(key: String) -> Bool { + let oldArguments = rawArguments + rawArguments = oldArguments.filter { $0 != .key(key) } + + return rawArguments.count < oldArguments.count + } + + /// Returns whether the given flag was specified and removes it from the + /// list of arguments remaining. + internal func consumeBoolean(flag: Character) -> Bool { + for (index, arg) in rawArguments.enumerated() { + if case let .flag(flags) = arg, flags.contains(flag) { + var flags = flags + flags.remove(flag) + + if flags.isEmpty { + rawArguments.remove(at: index) + } else { + rawArguments[index] = .flag(flags) + } + + return true + } + } + + return false + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentProtocol.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentProtocol.swift new file mode 100644 index 0000000..cf73b25 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/ArgumentProtocol.swift @@ -0,0 +1,44 @@ +// +// ArgumentProtocol.swift +// Commandant +// +// Created by Syo Ikeda on 12/14/15. +// Copyright (c) 2015 Carthage. All rights reserved. +// + +/// Represents a value that can be converted from a command-line argument. +public protocol ArgumentProtocol { + /// A human-readable name for this type. + static var name: String { get } + + /// Attempts to parse a value from the given command-line argument. + static func from(string: String) -> Self? +} + +extension Int: ArgumentProtocol { + public static let name = "integer" + + public static func from(string: String) -> Int? { + return Int(string) + } +} + +extension String: ArgumentProtocol { + public static let name = "string" + + public static func from(string: String) -> String? { + return string + } +} + +extension RawRepresentable where RawValue: StringProtocol, Self: ArgumentProtocol { + public static func from(string: String) -> Self? { + return RawValue(string).flatMap(Self.init(rawValue:)) + } +} + +extension RawRepresentable where RawValue: FixedWidthInteger, Self: ArgumentProtocol { + public static func from(string: String) -> Self? { + return RawValue(string).flatMap(Self.init(rawValue:)) + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Command.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/Command.swift new file mode 100644 index 0000000..ff65ca8 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Command.swift @@ -0,0 +1,223 @@ +// +// Command.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-10-10. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +import Foundation +import Result + +/// Represents a subcommand that can be executed with its own set of arguments. +public protocol CommandProtocol { + + /// The command's options type. + associatedtype Options: OptionsProtocol + + associatedtype ClientError: Error = Options.ClientError + + /// The action that users should specify to use this subcommand (e.g., + /// `help`). + var verb: String { get } + + /// A human-readable, high-level description of what this command is used + /// for. + var function: String { get } + + /// Runs this subcommand with the given options. + func run(_ options: Options) -> Result<(), ClientError> +} + +/// A type-erased command. +public struct CommandWrapper { + public let verb: String + public let function: String + + public let run: (ArgumentParser) -> Result<(), CommandantError> + + public let usage: () -> CommandantError? + + /// Creates a command that wraps another. + fileprivate init(_ command: C) where C.ClientError == ClientError, C.Options.ClientError == ClientError { + verb = command.verb + function = command.function + run = { (arguments: ArgumentParser) -> Result<(), CommandantError> in + let options = C.Options.evaluate(.arguments(arguments)) + + if let remainingArguments = arguments.remainingArguments { + return .failure(unrecognizedArgumentsError(remainingArguments)) + } + + switch options { + case let .success(options): + return command + .run(options) + .mapError(CommandantError.commandError) + + case let .failure(error): + return .failure(error) + } + } + usage = { () -> CommandantError? in + return C.Options.evaluate(.usage).error + } + } +} + +/// Describes the "mode" in which a command should run. +public enum CommandMode { + /// Options should be parsed from the given command-line arguments. + case arguments(ArgumentParser) + + /// Each option should record its usage information in an error, for + /// presentation to the user. + case usage +} + +/// Maintains the list of commands available to run. +public final class CommandRegistry { + private var commandsByVerb: [String: CommandWrapper] = [:] + + /// All available commands. + public var commands: [CommandWrapper] { + return commandsByVerb.values.sorted { return $0.verb < $1.verb } + } + + public init() {} + + /// Registers the given commands, making those available to run. + /// + /// If another commands were already registered with the same `verb`s, those + /// will be overwritten. + @discardableResult + public func register(_ commands: C...) + -> CommandRegistry + where C.ClientError == ClientError, C.Options.ClientError == ClientError + { + for command in commands { + commandsByVerb[command.verb] = CommandWrapper(command) + } + return self + } + + /// Runs the command corresponding to the given verb, passing it the given + /// arguments. + /// + /// Returns the results of the execution, or nil if no such command exists. + public func run(command verb: String, arguments: [String]) -> Result<(), CommandantError>? { + return self[verb]?.run(ArgumentParser(arguments)) + } + + /// Returns the command matching the given verb, or nil if no such command + /// is registered. + public subscript(verb: String) -> CommandWrapper? { + return commandsByVerb[verb] + } +} + +extension CommandRegistry { + /// Hands off execution to the CommandRegistry, by parsing CommandLine.arguments + /// and then running whichever command has been identified in the argument + /// list. + /// + /// If the chosen command executes successfully, the process will exit with + /// a successful exit code. + /// + /// If the chosen command fails, the provided error handler will be invoked, + /// then the process will exit with a failure exit code. + /// + /// If a matching command could not be found but there is any `executable-verb` + /// style subcommand executable in the caller's `$PATH`, the subcommand will + /// be executed. + /// + /// If a matching command could not be found or a usage error occurred, + /// a helpful error message will be written to `stderr`, then the process + /// will exit with a failure error code. + public func main(defaultVerb: String, errorHandler: (ClientError) -> ()) -> Never { + main(arguments: CommandLine.arguments, defaultVerb: defaultVerb, errorHandler: errorHandler) + } + + /// Hands off execution to the CommandRegistry, by parsing `arguments` + /// and then running whichever command has been identified in the argument + /// list. + /// + /// If the chosen command executes successfully, the process will exit with + /// a successful exit code. + /// + /// If the chosen command fails, the provided error handler will be invoked, + /// then the process will exit with a failure exit code. + /// + /// If a matching command could not be found but there is any `executable-verb` + /// style subcommand executable in the caller's `$PATH`, the subcommand will + /// be executed. + /// + /// If a matching command could not be found or a usage error occurred, + /// a helpful error message will be written to `stderr`, then the process + /// will exit with a failure error code. + public func main(arguments: [String], defaultVerb: String, errorHandler: (ClientError) -> ()) -> Never { + assert(arguments.count >= 1) + + var arguments = arguments + + // Extract the executable name. + let executableName = arguments.remove(at: 0) + + // use the default verb even if we have other arguments + var verb = defaultVerb + if let argument = arguments.first, !argument.hasPrefix("-") { + verb = argument + // Remove the command name. + arguments.remove(at: 0) + } + + switch run(command: verb, arguments: arguments) { + case .success?: + exit(EXIT_SUCCESS) + + case let .failure(error)?: + switch error { + case let .usageError(description): + fputs(description + "\n", stderr) + + case let .commandError(error): + errorHandler(error) + } + + exit(EXIT_FAILURE) + + case nil: + if let subcommandExecuted = executeSubcommandIfExists(executableName, verb: verb, arguments: arguments) { + exit(subcommandExecuted) + } + + fputs("Unrecognized command: '\(verb)'. See `\(executableName) help`.\n", stderr) + exit(EXIT_FAILURE) + } + } + + /// Finds and executes a subcommand which exists in your $PATH. The executable + /// name must be in the form of `executable-verb`. + /// + /// - Returns: The exit status of found subcommand or nil. + private func executeSubcommandIfExists(_ executableName: String, verb: String, arguments: [String]) -> Int32? { + let subcommand = "\(NSString(string: executableName).lastPathComponent)-\(verb)" + + func launchTask(_ path: String, arguments: [String]) -> Int32 { + let task = Process() + task.launchPath = path + task.arguments = arguments + + task.launch() + task.waitUntilExit() + + return task.terminationStatus + } + + guard launchTask("/usr/bin/which", arguments: [ "-s", subcommand ]) == 0 else { + return nil + } + + return launchTask("/usr/bin/env", arguments: [ subcommand ] + arguments) + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Commandant.h b/Carthage/Checkouts/Commandant/Sources/Commandant/Commandant.h new file mode 100644 index 0000000..4507251 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Commandant.h @@ -0,0 +1,17 @@ +// +// Commandant.h +// Commandant +// +// Created by Justin Spahr-Summers on 2014-11-21. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +#import + +//! Project version number for Commandant. +FOUNDATION_EXPORT double CommandantVersionNumber; + +//! Project version string for Commandant. +FOUNDATION_EXPORT const unsigned char CommandantVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Errors.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/Errors.swift new file mode 100644 index 0000000..f54bff0 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Errors.swift @@ -0,0 +1,158 @@ +// +// Errors.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-10-24. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +import Foundation +import Result + +/// Possible errors that can originate from Commandant. +/// +/// `ClientError` should be the type of error (if any) that can occur when +/// running commands. +public enum CommandantError: Error { + /// An option was used incorrectly. + case usageError(description: String) + + /// An error occurred while running a command. + case commandError(ClientError) +} + +extension CommandantError: CustomStringConvertible { + public var description: String { + switch self { + case let .usageError(description): + return description + + case let .commandError(error): + return String(describing: error) + } + } +} + +/// Constructs an `InvalidArgument` error that indicates a missing value for +/// the argument by the given name. +internal func missingArgumentError(_ argumentName: String) -> CommandantError { + let description = "Missing argument for \(argumentName)" + return .usageError(description: description) +} + +/// Constructs an error by combining the example of key (and value, if applicable) +/// with the usage description. +internal func informativeUsageError(_ keyValueExample: String, usage: String) -> CommandantError { + let lines = usage.components(separatedBy: .newlines) + + return .usageError(description: lines.reduce(keyValueExample) { previous, value in + return previous + "\n\t" + value + }) +} + +/// Combines the text of the two errors, if they're both `UsageError`s. +/// Otherwise, uses whichever one is not (biased toward the left). +internal func combineUsageErrors(_ lhs: CommandantError, _ rhs: CommandantError) -> CommandantError { + switch (lhs, rhs) { + case let (.usageError(left), .usageError(right)): + let combinedDescription = "\(left)\n\n\(right)" + return .usageError(description: combinedDescription) + + case (.usageError, _): + return rhs + + case (_, .usageError), (_, _): + return lhs + } +} + +/// Constructs an error that indicates unrecognized arguments remains. +internal func unrecognizedArgumentsError(_ options: [String]) -> CommandantError { + return .usageError(description: "Unrecognized arguments: " + options.joined(separator: ", ")) +} + +// MARK: Argument + +/// Constructs an error that describes how to use the argument, with the given +/// example of value usage if applicable. +internal func informativeUsageError(_ valueExample: String, argument: Argument) -> CommandantError { + if argument.defaultValue != nil { + return informativeUsageError("[\(valueExample)]", usage: argument.usage) + } else { + return informativeUsageError(valueExample, usage: argument.usage) + } +} + +/// Constructs an error that describes how to use the argument. +internal func informativeUsageError(_ argument: Argument) -> CommandantError { + var example = "" + + var valueExample = "" + if argument.usageParameter != nil { + valueExample = argument.usageParameterDescription + } else if let defaultValue = argument.defaultValue { + valueExample = "\(defaultValue)" + } + + if valueExample.isEmpty { + example += "(\(T.name))" + } else { + example += valueExample + } + + return informativeUsageError(example, argument: argument) +} + +/// Constructs an error that describes how to use the argument list. +internal func informativeUsageError(_ argument: Argument<[T]>) -> CommandantError { + var example = "" + + var valueExample = "" + if argument.usageParameter != nil { + valueExample = argument.usageParameterDescription + } else if let defaultValue = argument.defaultValue { + valueExample = "\(defaultValue)" + } + + if valueExample.isEmpty { + example += "(\(T.name))" + } else { + example += valueExample + } + + return informativeUsageError(example, argument: argument) +} + +// MARK: Option + +/// Constructs an error that describes how to use the option, with the given +/// example of key (and value, if applicable) usage. +internal func informativeUsageError(_ keyValueExample: String, option: Option) -> CommandantError { + return informativeUsageError("[\(keyValueExample)]", usage: option.usage) +} + +/// Constructs an error that describes how to use the option. +internal func informativeUsageError(_ option: Option) -> CommandantError { + return informativeUsageError("--\(option.key) \(option.defaultValue)", option: option) +} + +/// Constructs an error that describes how to use the option. +internal func informativeUsageError(_ option: Option) -> CommandantError { + return informativeUsageError("--\(option.key) (\(T.name))", option: option) +} + +/// Constructs an error that describes how to use the option. +internal func informativeUsageError(_ option: Option<[T]>) -> CommandantError { + return informativeUsageError("--\(option.key) (\(option.defaultValue))", option: option) +} + +/// Constructs an error that describes how to use the option. +internal func informativeUsageError(_ option: Option<[T]?>) -> CommandantError { + return informativeUsageError("--\(option.key) (\(T.name))", option: option) +} + +/// Constructs an error that describes how to use the given boolean option. +internal func informativeUsageError(_ option: Option) -> CommandantError { + let key = option.key + return informativeUsageError((option.defaultValue ? "--no-\(key)" : "--\(key)"), option: option) +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/HelpCommand.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/HelpCommand.swift new file mode 100644 index 0000000..b07ba63 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/HelpCommand.swift @@ -0,0 +1,76 @@ +// +// HelpCommand.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-10-10. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +import Foundation +import Result + +/// A basic implementation of a `help` command, using information available in a +/// `CommandRegistry`. +/// +/// If you want to use this command, initialize it with the registry, then add +/// it to that same registry: +/// +/// let commands: CommandRegistry = … +/// let helpCommand = HelpCommand(registry: commands) +/// commands.register(helpCommand) +public struct HelpCommand: CommandProtocol { + public typealias Options = HelpOptions + + public let verb = "help" + public let function = "Display general or command-specific help" + + private let registry: CommandRegistry + + /// Initializes the command to provide help from the given registry of + /// commands. + public init(registry: CommandRegistry) { + self.registry = registry + } + + public func run(_ options: Options) -> Result<(), ClientError> { + if let verb = options.verb { + if let command = self.registry[verb] { + print(command.function) + if let usageError = command.usage() { + print("\n\(usageError)") + } + return .success(()) + } else { + fputs("Unrecognized command: '\(verb)'\n", stderr) + } + } + + print("Available commands:\n") + + let maxVerbLength = self.registry.commands.map { $0.verb.count }.max() ?? 0 + + for command in self.registry.commands { + let padding = repeatElement(Character(" "), count: maxVerbLength - command.verb.count) + print(" \(command.verb)\(String(padding)) \(command.function)") + } + + return .success(()) + } +} + +public struct HelpOptions: OptionsProtocol { + fileprivate let verb: String? + + private init(verb: String?) { + self.verb = verb + } + + private static func create(_ verb: String) -> HelpOptions { + return self.init(verb: (verb == "" ? nil : verb)) + } + + public static func evaluate(_ m: CommandMode) -> Result> { + return create + <*> m <| Argument(defaultValue: "", usage: "the command to display help for") + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Info.plist b/Carthage/Checkouts/Commandant/Sources/Commandant/Info.plist new file mode 100644 index 0000000..b3edca9 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.15.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2014 Carthage. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Option.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/Option.swift new file mode 100644 index 0000000..9069a8a --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Option.swift @@ -0,0 +1,274 @@ +// +// Option.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-11-21. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +import Foundation +import Result + +/// Represents a record of options for a command, which can be parsed from +/// a list of command-line arguments. +/// +/// This is most helpful when used in conjunction with the `Option` and `Switch` +/// types, and `<*>` and `<|` combinators. +/// +/// Example: +/// +/// struct LogOptions: OptionsProtocol { +/// let verbosity: Int +/// let outputFilename: String +/// let shouldDelete: Bool +/// let logName: String +/// +/// static func create(_ verbosity: Int) -> (String) -> (Bool) -> (String) -> LogOptions { +/// return { outputFilename in { shouldDelete in { logName in LogOptions(verbosity: verbosity, outputFilename: outputFilename, shouldDelete: shouldDelete, logName: logName) } } } +/// } +/// +/// static func evaluate(_ m: CommandMode) -> Result> { +/// return create +/// <*> m <| Option(key: "verbose", defaultValue: 0, usage: "the verbosity level with which to read the logs") +/// <*> m <| Option(key: "outputFilename", defaultValue: "", usage: "a file to print output to, instead of stdout") +/// <*> m <| Switch(flag: "d", key: "delete", usage: "delete the logs when finished") +/// <*> m <| Argument(usage: "the log to read") +/// } +/// } +public protocol OptionsProtocol { + associatedtype ClientError: Error + + /// Evaluates this set of options in the given mode. + /// + /// Returns the parsed options or a `UsageError`. + static func evaluate(_ m: CommandMode) -> Result> +} + +/// An `OptionsProtocol` that has no options. +public struct NoOptions: OptionsProtocol { + public init() {} + + public static func evaluate(_ m: CommandMode) -> Result> { + return .success(NoOptions()) + } +} + +/// Describes an option that can be provided on the command line. +public struct Option { + /// The key that controls this option. For example, a key of `verbose` would + /// be used for a `--verbose` option. + public let key: String + + /// The default value for this option. This is the value that will be used + /// if the option is never explicitly specified on the command line. + public let defaultValue: T + + /// A human-readable string describing the purpose of this option. This will + /// be shown in help messages. + /// + /// For boolean operations, this should describe the effect of _not_ using + /// the default value (i.e., what will happen if you disable/enable the flag + /// differently from the default). + public let usage: String + + public init(key: String, defaultValue: T, usage: String) { + self.key = key + self.defaultValue = defaultValue + self.usage = usage + } +} + +extension Option: CustomStringConvertible { + public var description: String { + return "--\(key)" + } +} + +// MARK: - Operators + +// Inspired by the Argo library: +// https://github.com/thoughtbot/Argo +/* + Copyright (c) 2014 thoughtbot, inc. + + MIT License + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +infix operator <*> : LogicalDisjunctionPrecedence + +infix operator <| : MultiplicationPrecedence + +/// Applies `f` to the value in the given result. +/// +/// In the context of command-line option parsing, this is used to chain +/// together the parsing of multiple arguments. See OptionsProtocol for an example. +public func <*> (f: (T) -> U, value: Result>) -> Result> { + return value.map(f) +} + +/// Applies the function in `f` to the value in the given result. +/// +/// In the context of command-line option parsing, this is used to chain +/// together the parsing of multiple arguments. See OptionsProtocol for an example. +public func <*> (f: Result<((T) -> U), CommandantError>, value: Result>) -> Result> { + switch (f, value) { + case let (.failure(left), .failure(right)): + return .failure(combineUsageErrors(left, right)) + + case let (.failure(left), .success): + return .failure(left) + + case let (.success, .failure(right)): + return .failure(right) + + case let (.success(f), .success(value)): + let newValue = f(value) + return .success(newValue) + } +} + +extension CommandMode { + /// Evaluates the given option in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the option's `defaultValue` is used. + public static func <| (mode: CommandMode, option: Option) -> Result> { + let wrapped = Option(key: option.key, defaultValue: option.defaultValue, usage: option.usage) + // Since we are passing a non-nil default value, we can safely unwrap the + // result. + return (mode <| wrapped).map { $0! } + } + + /// Evaluates the given option in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, `nil` is used. + public static func <| (mode: CommandMode, option: Option) -> Result> { + let key = option.key + switch mode { + case let .arguments(arguments): + var stringValue: String? + switch arguments.consumeValue(forKey: key) { + case let .success(value): + stringValue = value + + case let .failure(error): + switch error { + case let .usageError(description): + return .failure(.usageError(description: description)) + + case .commandError: + fatalError("CommandError should be impossible when parameterized over NoError") + } + } + + if let stringValue = stringValue { + if let value = T.from(string: stringValue) { + return .success(value) + } + + let description = "Invalid value for '--\(key)': \(stringValue)" + return .failure(.usageError(description: description)) + } else { + return .success(option.defaultValue) + } + + case .usage: + return .failure(informativeUsageError(option)) + } + } + + /// Evaluates the given option in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the option's `defaultValue` is used. + public static func <| (mode: CommandMode, option: Option<[T]>) -> Result<[T], CommandantError> { + let wrapped = Option<[T]?>(key: option.key, defaultValue: option.defaultValue, usage: option.usage) + // Since we are passing a non-nil default value, we can safely unwrap the + // result. + return (mode <| wrapped).map { $0! } + } + + /// Evaluates the given option in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, `nil` is used. + public static func <| (mode: CommandMode, option: Option<[T]?>) -> Result<[T]?, CommandantError> { + let key = option.key + + switch mode { + case let .arguments(arguments): + let stringValue: String? + switch arguments.consumeValue(forKey: key) { + case let .success(value): + stringValue = value + + case let .failure(error): + switch error { + case let .usageError(description): + return .failure(.usageError(description: description)) + + case .commandError: + fatalError("CommandError should be impossible when parameterized over NoError") + } + } + + guard let unwrappedStringValue = stringValue else { + return .success(option.defaultValue) + } + + let components = unwrappedStringValue.split( + omittingEmptySubsequences: true, + whereSeparator: [",", " "].contains + ) + var resultValues: [T] = [] + for component in components { + guard let value = T.from(string: String(component)) else { + let description = "Invalid value for '--\(key)': \(unwrappedStringValue)" + return .failure(.usageError(description: description)) + } + resultValues.append(value) + } + return .success(resultValues) + + case .usage: + return .failure(informativeUsageError(option)) + } + } + + /// Evaluates the given boolean option in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the option's `defaultValue` is used. + public static func <| (mode: CommandMode, option: Option) -> Result> { + switch mode { + case let .arguments(arguments): + if let value = arguments.consumeBoolean(forKey: option.key) { + return .success(value) + } else { + return .success(option.defaultValue) + } + + case .usage: + return .failure(informativeUsageError(option)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/OrderedSet.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/OrderedSet.swift new file mode 100644 index 0000000..6038637 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/OrderedSet.swift @@ -0,0 +1,53 @@ +/// A poor man's ordered set. +internal struct OrderedSet: Equatable { + fileprivate var values: [T] = [] + + init(_ sequence: S) where S.Element == T { + for e in sequence where !values.contains(e) { + values.append(e) + } + } + + @discardableResult + mutating func remove(_ member: T) -> T? { + if let index = values.index(of: member) { + return values.remove(at: index) + } else { + return nil + } + } +} + +#if !swift(>=4.1) +extension OrderedSet { + static func == (_ lhs: OrderedSet, rhs: OrderedSet) -> Bool { + return lhs.values == rhs.values + } +} +#endif + +extension OrderedSet: Collection { + subscript(position: Int) -> T { + return values[position] + } + + var count: Int { + return values.count + } + + var isEmpty: Bool { + return values.isEmpty + } + + var startIndex: Int { + return values.startIndex + } + + var endIndex: Int { + return values.endIndex + } + + func index(after i: Int) -> Int { + return values.index(after: i) + } +} diff --git a/Carthage/Checkouts/Commandant/Sources/Commandant/Switch.swift b/Carthage/Checkouts/Commandant/Sources/Commandant/Switch.swift new file mode 100644 index 0000000..5ed21ad --- /dev/null +++ b/Carthage/Checkouts/Commandant/Sources/Commandant/Switch.swift @@ -0,0 +1,69 @@ +// +// Switch.swift +// Commandant +// +// Created by Neil Pankey on 3/31/15. +// Copyright (c) 2015 Carthage. All rights reserved. +// + +import Result + +/// Describes a parameterless command line flag that defaults to false and can only +/// be switched on. Canonical examples include `--force` and `--recurse`. +/// +/// For a boolean toggle that can be enabled and disabled use `Option`. +public struct Switch { + /// The key that enables this switch. For example, a key of `verbose` would be + /// used for a `--verbose` option. + public let key: String + + /// Optional single letter flag that enables this switch. For example, `-v` would + /// be used as a shorthand for `--verbose`. + /// + /// Multiple flags can be grouped together as a single argument and will split + /// when parsing (e.g. `rm -rf` treats 'r' and 'f' as inidividual flags). + public let flag: Character? + + /// A human-readable string describing the purpose of this option. This will + /// be shown in help messages. + public let usage: String + + public init(flag: Character? = nil, key: String, usage: String) { + self.flag = flag + self.key = key + self.usage = usage + } +} + +extension Switch: CustomStringConvertible { + public var description: String { + var options = "--\(key)" + if let flag = self.flag { + options += "|-\(flag)" + } + return options + } +} + +// MARK: - Operators + +extension CommandMode { + /// Evaluates the given boolean switch in the given mode. + /// + /// If parsing command line arguments, and no value was specified on the command + /// line, the option's `defaultValue` is used. + public static func <| (mode: CommandMode, option: Switch) -> Result> { + switch mode { + case let .arguments(arguments): + var enabled = arguments.consume(key: option.key) + + if let flag = option.flag, !enabled { + enabled = arguments.consumeBoolean(flag: flag) + } + return .success(enabled) + + case .usage: + return .failure(informativeUsageError(option.description, usage: option.usage)) + } + } +} diff --git a/Carthage/Checkouts/Commandant/Tests/CommandantTests/CommandSpec.swift b/Carthage/Checkouts/Commandant/Tests/CommandantTests/CommandSpec.swift new file mode 100644 index 0000000..1e18990 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/CommandantTests/CommandSpec.swift @@ -0,0 +1,38 @@ +// +// CommandSpec.swift +// Commandant +// +// Created by Syo Ikeda on 1/5/16. +// Copyright © 2016 Carthage. All rights reserved. +// + +import Commandant +import Nimble +import Quick +import Result + +class CommandWrapperSpec: QuickSpec { + override func spec() { + describe("CommandWrapper.usage") { + it("should not crash for a command with NoOptions") { + let command = NoOptionsCommand() + + let registry = CommandRegistry>() + registry.register(command) + + let wrapper = registry[command.verb] + expect(wrapper).notTo(beNil()) + expect(wrapper?.usage()).to(beNil()) + } + } + } +} + +struct NoOptionsCommand: CommandProtocol { + var verb: String { return "verb" } + var function: String { return "function" } + + func run(_ options: NoOptions>) -> Result<(), CommandantError<()>> { + return .success(()) + } +} diff --git a/Carthage/Checkouts/Commandant/Tests/CommandantTests/Info.plist b/Carthage/Checkouts/Commandant/Tests/CommandantTests/Info.plist new file mode 100644 index 0000000..cb62578 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/CommandantTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 0.15.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionSpec.swift b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionSpec.swift new file mode 100644 index 0000000..d75b8e1 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionSpec.swift @@ -0,0 +1,195 @@ +// +// OptionSpec.swift +// Commandant +// +// Created by Justin Spahr-Summers on 2014-10-25. +// Copyright (c) 2014 Carthage. All rights reserved. +// + +@testable import Commandant +import Foundation +import Nimble +import Quick +import Result + +class OptionsProtocolSpec: QuickSpec { + override func spec() { + describe("CommandMode.Arguments") { + func tryArguments(_ arguments: String...) -> Result> { + return TestOptions.evaluate(.arguments(ArgumentParser(arguments))) + } + + it("should fail if a required argument is missing") { + expect(tryArguments().value).to(beNil()) + } + + it("should fail if an option is missing a value") { + expect(tryArguments("required", "--intValue").value).to(beNil()) + } + + it("should succeed without optional string arguments") { + let value = tryArguments("required").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by comma") { + let value = tryArguments("required", "--intValue", "3", "--optionalStringValue", "baz", "fuzzbuzz", "--stringsArray", "a,b,c").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: ["a","b","c"], optionalStringsArray: nil, optionalStringValue: "baz", optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by space") { + let value = tryArguments("required", "--intValue", "3", "--optionalStringValue", "baz", "--stringsArray", "a b c", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: ["a", "b", "c"], optionalStringsArray: nil, optionalStringValue: "baz", optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by comma and space") { + let value = tryArguments("required", "--intValue", "3", "--optionalStringValue", "baz", "--stringsArray", "a, b, c", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: ["a", "b", "c"], optionalStringsArray: nil, optionalStringValue: "baz", optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some optional string arguments") { + let value = tryArguments("required", "--intValue", "3", "--optionalStringValue", "baz", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: "baz", optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed without optional array arguments") { + let value = tryArguments("required").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some optional array arguments") { + let value = tryArguments("required", "--intValue", "3", "--optionalStringsArray", "one, two", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: [], optionalStringsArray: ["one", "two"], optionalStringValue: nil, optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should override previous optional arguments") { + let value = tryArguments("required", "--intValue", "3", "--stringValue", "fuzzbuzz", "--intValue", "5", "--stringValue", "bazbuzz").value + let expected = TestOptions(intValue: 5, stringValue: "bazbuzz", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should enable a boolean flag") { + let value = tryArguments("required", "--enabled", "--intValue", "3", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "fuzzbuzz", requiredName: "required", enabled: true, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should re-disable a boolean flag") { + let value = tryArguments("required", "--enabled", "--no-enabled", "--intValue", "3", "fuzzbuzz").value + let expected = TestOptions(intValue: 3, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "fuzzbuzz", requiredName: "required", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should enable a boolean flag if a single Switch flag is passed") { + let value = tryArguments("required", "-f").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: true, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should enable multiple boolean flags if multiple grouped Switch flags are passed") { + let value = tryArguments("required", "-fg").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: true, glob: true, arguments: []) + expect(value).to(equal(expected)) + } + + it("should enable a boolean flag if a single Switch key is passed") { + let value = tryArguments("required", "--force").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: true, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + + it("should enable multiple boolean flags if multiple Switch keys are passed") { + let value = tryArguments("required", "--force", "--glob").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "required", enabled: false, force: true, glob: true, arguments: []) + expect(value).to(equal(expected)) + } + + it("should consume the rest of positional arguments") { + let value = tryArguments("required", "optional", "value1", "value2").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "optional", requiredName: "required", enabled: false, force: false, glob: false, arguments: [ "value1", "value2" ]) + expect(value).to(equal(expected)) + } + + it("should treat -- as the end of valued options") { + let value = tryArguments("--", "--intValue").value + let expected = TestOptions(intValue: 42, stringValue: "foobar", stringsArray: [], optionalStringsArray: nil, optionalStringValue: nil, optionalFilename: "filename", requiredName: "--intValue", enabled: false, force: false, glob: false, arguments: []) + expect(value).to(equal(expected)) + } + } + + describe("CommandMode.Usage") { + it("should return an error containing usage information") { + let error = TestOptions.evaluate(.usage).error + expect(error?.description).to(contain("intValue")) + expect(error?.description).to(contain("stringValue")) + expect(error?.description).to(contain("name you're required to")) + expect(error?.description).to(contain("optionally specify")) + } + } + } +} + +struct TestOptions: OptionsProtocol, Equatable { + let intValue: Int + let stringValue: String + let stringsArray: [String] + let optionalStringsArray: [String]? + let optionalStringValue: String? + let optionalFilename: String + let requiredName: String + let enabled: Bool + let force: Bool + let glob: Bool + let arguments: [String] + + typealias ClientError = NoError + + static func create(_ a: Int) -> (String) -> ([String]) -> ([String]?) -> (String?) -> (String) -> (String) -> (Bool) -> (Bool) -> (Bool) -> ([String]) -> TestOptions { + return { b in { c in { d in { e in { f in { g in { h in { i in { j in { k in + return self.init(intValue: a, stringValue: b, stringsArray: c, optionalStringsArray: d, optionalStringValue: e, optionalFilename: g, requiredName: f, enabled: h, force: i, glob: j, arguments: k) + } } } } } } } } } } + } + + static func evaluate(_ m: CommandMode) -> Result> { + return create + <*> m <| Option(key: "intValue", defaultValue: 42, usage: "Some integer value") + <*> m <| Option(key: "stringValue", defaultValue: "foobar", usage: "Some string value") + <*> m <| Option<[String]>(key: "stringsArray", defaultValue: [], usage: "Some array of arguments") + <*> m <| Option<[String]?>(key: "optionalStringsArray", defaultValue: nil, usage: "Some array of arguments") + <*> m <| Option(key: "optionalStringValue", defaultValue: nil, usage: "Some string value") + <*> m <| Argument(usage: "A name you're required to specify") + <*> m <| Argument(defaultValue: "filename", usage: "A filename that you can optionally specify") + <*> m <| Option(key: "enabled", defaultValue: false, usage: "Whether to be enabled") + <*> m <| Switch(flag: "f", key: "force", usage: "Whether to force") + <*> m <| Switch(flag: "g", key: "glob", usage: "Whether to glob") + <*> m <| Argument(defaultValue: [], usage: "An argument list that consumes the rest of positional arguments") + } +} + +func ==(lhs: TestOptions, rhs: TestOptions) -> Bool { + return lhs.intValue == rhs.intValue && lhs.stringValue == rhs.stringValue && lhs.stringsArray == rhs.stringsArray && lhs.optionalStringsArray == rhs.optionalStringsArray && lhs.optionalStringValue == rhs.optionalStringValue && lhs.optionalFilename == rhs.optionalFilename && lhs.requiredName == rhs.requiredName && lhs.enabled == rhs.enabled && lhs.force == rhs.force && lhs.glob == rhs.glob && lhs.arguments == rhs.arguments +} + +func ==(lhs: [T]?, rhs: [T]?) -> Bool { + switch (lhs,rhs) { + case let (lhs?, rhs?): + return lhs == rhs + case (nil, nil): + return true + default: + return false + } +} + +extension TestOptions: CustomStringConvertible { + var description: String { + return "{ intValue: \(intValue), stringValue: \(stringValue), stringsArray: \(stringsArray), optionalStringsArray: \(String(describing: optionalStringsArray)), optionalStringValue: \(String(describing: optionalStringValue)), optionalFilename: \(optionalFilename), requiredName: \(requiredName), enabled: \(enabled), force: \(force), glob: \(glob), arguments: \(arguments) }" + } +} diff --git a/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionsWithEnumProtocolSpec.swift b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionsWithEnumProtocolSpec.swift new file mode 100644 index 0000000..650a17c --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OptionsWithEnumProtocolSpec.swift @@ -0,0 +1,179 @@ +// +// OptionsWithEnumProtocolSpec.swift +// Commandant +// +// Created by Vitalii Budnik on 11/22/17. +// Copyright © 2017 Carthage. All rights reserved. +// + +@testable import Commandant +import Foundation +import Nimble +import Quick +import Result + +class OptionsWithEnumProtocolSpec: QuickSpec { + override func spec() { + describe("CommandMode.Arguments") { + func tryArguments(_ arguments: String...) -> Result> { + return TestEnumOptions.evaluate(.arguments(ArgumentParser(arguments))) + } + + it("should fail if a required argument is missing") { + expect(tryArguments().value).to(beNil()) + } + + it("should fail if an option is missing a value") { + expect(tryArguments("required", "--strictIntValue").value).to(beNil()) + } + + it("should fail if an option is missing a value") { + expect(tryArguments("required", "--strictStringValue", "drop").value).to(beNil()) + } + + it("should fail if an optional strict int parameter is wrong") { + expect(tryArguments("required", "256").value).to(beNil()) + } + + it("should succeed without optional string arguments") { + let value = tryArguments("required").value + let expected = TestEnumOptions(strictIntValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .min, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed without optional strict int value") { + let value = tryArguments("required", "5").value + let expected = TestEnumOptions(strictIntValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .giveFive, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by comma") { + let value = tryArguments("required", "--strictIntValue", "3", "--optionalStrictStringValue", "baz", "255", "--strictStringsArray", "a,b,c").value + let expected = TestEnumOptions(strictIntValue: .three, strictStringValue: .foobar, strictStringsArray: [.a, .b, .c], optionalStrictStringsArray: nil, optionalStrictStringValue: .baz, optionalStrictInt: .max, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by space") { + let value = tryArguments("required", "--strictIntValue", "3", "--optionalStrictStringValue", "baz", "--strictStringsArray", "a b c", "255").value + let expected = TestEnumOptions(strictIntValue: .three, strictStringValue: .foobar, strictStringsArray: [.a, .b, .c], optionalStrictStringsArray: nil, optionalStrictStringValue: .baz, optionalStrictInt: .max, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some strings array arguments separated by comma and space") { + let value = tryArguments("required", "--strictIntValue", "3", "--optionalStrictStringValue", "baz", "--strictStringsArray", "a, b, c", "255").value + let expected = TestEnumOptions(strictIntValue: .three, strictStringValue: .foobar, strictStringsArray: [.a, .b, .c], optionalStrictStringsArray: nil, optionalStrictStringValue: .baz, optionalStrictInt: .max, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some optional string arguments") { + let value = tryArguments("required", "--strictIntValue", "3", "--optionalStrictStringValue", "baz", "255").value + let expected = TestEnumOptions(strictIntValue: .three, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: .baz, optionalStrictInt: .max, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed without optional array arguments") { + let value = tryArguments("required").value + let expected = TestEnumOptions(strictIntValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .min, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should succeed with some optional array arguments") { + let value = tryArguments("required", "--strictIntValue", "3", "--optionalStrictStringsArray", "one, two", "255").value + let expected = TestEnumOptions(strictIntValue: .three, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: [.one, .two], optionalStrictStringValue: nil, optionalStrictInt: .max, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should override previous optional arguments") { + let value = tryArguments("required", "--strictIntValue", "3", "--strictStringValue", "fuzzbuzz", "--strictIntValue", "5", "--strictStringValue", "bazbuzz").value + let expected = TestEnumOptions(strictIntValue: .giveFive, strictStringValue: .bazbuzz, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .min, requiredName: "required", arguments: []) + expect(value).to(equal(expected)) + } + + it("should consume the rest of positional arguments") { + let value = tryArguments("required", "255", "value1", "value2").value + let expected = TestEnumOptions(strictIntValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .max, requiredName: "required", arguments: [ "value1", "value2" ]) + expect(value).to(equal(expected)) + } + + it("should treat -- as the end of valued options") { + let value = tryArguments("--", "--strictIntValue").value + let expected = TestEnumOptions(strictIntValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, strictStringValue: .foobar, strictStringsArray: [], optionalStrictStringsArray: nil, optionalStrictStringValue: nil, optionalStrictInt: .min, requiredName: "--strictIntValue", arguments: []) + expect(value).to(equal(expected)) + } + } + + describe("CommandMode.Usage") { + it("should return an error containing usage information") { + let error = TestEnumOptions.evaluate(.usage).error + expect(error?.description).to(contain("strictIntValue")) + expect(error?.description).to(contain("strictStringValue")) + expect(error?.description).to(contain("name you're required to")) + expect(error?.description).to(contain("optionally specify")) + } + } + } +} + +struct TestEnumOptions: OptionsProtocol, Equatable { + let strictIntValue: StrictIntValue + let strictStringValue: StrictStringValue + let strictStringsArray: [StrictStringValue] + let optionalStrictStringsArray: [StrictStringValue]? + let optionalStrictStringValue: StrictStringValue? + let optionalStrictInt: StrictIntValue + let requiredName: String + let arguments: [String] + + typealias ClientError = NoError + + static func create(_ a: StrictIntValue) -> (StrictStringValue) -> ([StrictStringValue]) -> ([StrictStringValue]?) -> (StrictStringValue?) -> (String) -> (StrictIntValue) -> ([String]) -> TestEnumOptions { + return { b in { c in { d in { e in { f in { g in { h in + return self.init(strictIntValue: a, strictStringValue: b, strictStringsArray: c, optionalStrictStringsArray: d, optionalStrictStringValue: e, optionalStrictInt: g, requiredName: f, arguments: h) + } } } } } } } + } + + static func evaluate(_ m: CommandMode) -> Result> { + return create + <*> m <| Option(key: "strictIntValue", defaultValue: .theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything, usage: "`0` - zero, `255` - max, `3` - three, `5` - five or `42` - The Answer") + <*> m <| Option(key: "strictStringValue", defaultValue: .foobar, usage: "`foobar`, `bazbuzzz`, `a`, `b`, `c`, `one`, `two`, `c`") + <*> m <| Option<[StrictStringValue]>(key: "strictStringsArray", defaultValue: [], usage: "Some array of arguments") + <*> m <| Option<[StrictStringValue]?>(key: "optionalStrictStringsArray", defaultValue: nil, usage: "Some array of arguments") + <*> m <| Option(key: "optionalStrictStringValue", defaultValue: nil, usage: "Some string value") + <*> m <| Argument(usage: "A name you're required to specify") + <*> m <| Argument(defaultValue: .min, usage: "A number that you can optionally specify") + <*> m <| Argument(defaultValue: [], usage: "An argument list that consumes the rest of positional arguments") + } +} + +func ==(lhs: TestEnumOptions, rhs: TestEnumOptions) -> Bool { + return lhs.strictIntValue == rhs.strictIntValue && lhs.strictStringValue == rhs.strictStringValue && lhs.strictStringsArray == rhs.strictStringsArray && lhs.optionalStrictStringsArray == rhs.optionalStrictStringsArray && lhs.optionalStrictStringValue == rhs.optionalStrictStringValue && lhs.optionalStrictInt == rhs.optionalStrictInt && lhs.requiredName == rhs.requiredName && lhs.arguments == rhs.arguments +} + +extension TestEnumOptions: CustomStringConvertible { + var description: String { + return "{ strictIntValue: \(strictIntValue), strictStringValue: \(strictStringValue), strictStringsArray: \(strictStringsArray), optionalStrictStringsArray: \(String(describing: optionalStrictStringsArray)), optionalStrictStringValue: \(String(describing: optionalStrictStringValue)), optionalStrictInt: \(optionalStrictInt), requiredName: \(requiredName), arguments: \(arguments) }" + } +} + +enum StrictStringValue: String, ArgumentProtocol { + static var name: String = "Strict string value: `foobar`, `bazbuzz`, `one`, `two`, `baz`, `a`, `b` or `c`" + + case foobar + case bazbuzz + case one + case two + case baz + case a + case b + case c +} + +enum StrictIntValue: UInt8, ArgumentProtocol { + static var name: String = "Strict int value: `3`, `5`, `42`, `0`, `255`" + + case min = 0 + case three = 3 + case giveFive = 5 + case theAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything = 42 + case max = 255 +} diff --git a/Carthage/Checkouts/Commandant/Tests/CommandantTests/OrderedSetSpec.swift b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OrderedSetSpec.swift new file mode 100644 index 0000000..1533125 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/CommandantTests/OrderedSetSpec.swift @@ -0,0 +1,21 @@ +@testable import Commandant +import Foundation +import Quick +import Nimble + +class OrderedSetSpec: QuickSpec { + override func spec() { + describe("OrderedSet") { + it("should remove duplicate entries") { + let input = ["a", "c", "b", "a"] + let output = OrderedSet(input) + expect(output.count) == 3 + } + + it("should preserve the order of the given input") { + let input = ["a", "c", "b", "a"] + expect(OrderedSet(input).joined()) == "acb" + } + } + } +} diff --git a/Carthage/Checkouts/Commandant/Tests/LinuxMain.swift b/Carthage/Checkouts/Commandant/Tests/LinuxMain.swift new file mode 100644 index 0000000..8b54e63 --- /dev/null +++ b/Carthage/Checkouts/Commandant/Tests/LinuxMain.swift @@ -0,0 +1,11 @@ +import XCTest +import Quick + +@testable import CommandantTests + +Quick.QCKMain([ + CommandWrapperSpec.self, + OptionsProtocolSpec.self, + OptionsWithEnumProtocolSpec.self, + OrderedSetSpec.self, +]) diff --git a/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Nimble/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Nimble/.gitignore b/Carthage/Checkouts/Nimble/.gitignore new file mode 100644 index 0000000..6930efd --- /dev/null +++ b/Carthage/Checkouts/Nimble/.gitignore @@ -0,0 +1,29 @@ +.DS_Store +**/xcuserdata/* +**/*.xccheckout +**/*.xcscmblueprint +build/ +.idea +DerivedData/ +Nimble.framework.zip + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts +Carthage/Checkouts/**/*.* +Carthage/Checkouts/**/Cart* +Carthage/Checkouts/**/Tests +!Carthage/Checkouts/**/LICENSE.* +!Carthage/Checkouts/**/*.md +!Carthage/Checkouts/**/*.swift +!Carthage/Checkouts/**/*.h +!Carthage/Checkouts/**/*.m +!Carthage/Checkouts/**/*.c +Carthage/Build + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ diff --git a/Carthage/Checkouts/Nimble/.hound.yml b/Carthage/Checkouts/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Nimble/.swift-version b/Carthage/Checkouts/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/Nimble/.swiftlint.yml b/Carthage/Checkouts/Nimble/.swiftlint.yml new file mode 100644 index 0000000..cb105e7 --- /dev/null +++ b/Carthage/Checkouts/Nimble/.swiftlint.yml @@ -0,0 +1,19 @@ +disabled_rules: + - todo + - variable_name + - force_try + - force_cast + +included: + - Sources + - Tests + +excluded: + - Carthage/Checkouts + +trailing_comma: + mandatory_comma: true + +line_length: + ignores_comments: true + ignores_function_declarations: true diff --git a/Carthage/Checkouts/Nimble/.travis.yml b/Carthage/Checkouts/Nimble/.travis.yml new file mode 100644 index 0000000..23ce159 --- /dev/null +++ b/Carthage/Checkouts/Nimble/.travis.yml @@ -0,0 +1,51 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + sudo: required + env: TYPE=podspec + - os: osx + env: TYPE=ios NIMBLE_RUNTIME_IOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=tvos NIMBLE_RUNTIME_TVOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=macos + - os: osx + env: TYPE=macos + osx_image: xcode9 + - os: osx + env: TYPE=macos + osx_image: xcode9.1 + - os: osx + env: TYPE=macos + osx_image: xcode9.2 + - os: osx + env: TYPE=macos + osx_image: xcode9.3 + - os: osx + env: TYPE=macos + osx_image: xcode9.4 + - os: osx + env: TYPE=swiftpm + - os: osx + env: TYPE=swiftpm + osx_image: xcode9 + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + - os: linux + dist: trusty + sudo: required + env: + - TYPE=swiftpm + - SWIFT_VERSION=4.0.2 + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" +install: + - if [[ "$TYPE" == "podspec" ]]; then sudo gem install bundler; bundle install; fi +script: + - ./test $TYPE diff --git a/Carthage/Checkouts/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/Nimble/CONTRIBUTING.md @@ -0,0 +1,120 @@ + + + +- [Welcome to Nimble!](#welcome-to-nimble!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + + + +# Welcome to Nimble! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Nimble should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +**tl;dr:** If you've added a file to the project, make sure it's +included in both the OS X and iOS targets. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Nimble (eg - v2.0.0 or git sha `20a3f3b4e63cc8d97c92c4164bf36f2a2c9a6e1b`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- Use `Nimble.xcodeproj` to work on Nimble. + +## Running the Swift Package Manager tests + +1. Install `swiftenv` by running a line from the build script (`.travis.yml`): + + eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" + +2. Run `./test swiftpm` + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of Nimble + before submitting your pull request. You can run all the OS X & iOS unit + tests using `./test`. +- If you've added a file to the project, make sure it's included in both + the OS X and iOS targets. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +### Code of Conduct + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +### Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Nimble/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Update [Quick](https://github.com/Quick/Quick) + - Update Quick's submodule reference to the newly released Nimble version + - Update Nimble version in `README.md` and Documentation in [Quick](https://github.com/Quick/Quick) if it's not a patch version update. +- Announce! diff --git a/Carthage/Checkouts/Nimble/Cartfile.private b/Carthage/Checkouts/Nimble/Cartfile.private new file mode 100644 index 0000000..23d7e11 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Cartfile.private @@ -0,0 +1 @@ +github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" diff --git a/Carthage/Checkouts/Nimble/Cartfile.resolved b/Carthage/Checkouts/Nimble/Cartfile.resolved new file mode 100644 index 0000000..32a1c25 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Cartfile.resolved @@ -0,0 +1,2 @@ +github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923" +github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt new file mode 100644 index 0000000..ca8f5b8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift new file mode 100644 index 0000000..c1e2ed8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift @@ -0,0 +1,9 @@ +import PackageDescription + +let package = Package( + name: "CwlCatchException", + targets: [ + Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]), + Target(name: "CwlCatchExceptionSupport") + ] +) diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md new file mode 100644 index 0000000..0f97b03 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/README.md @@ -0,0 +1,46 @@ +# 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. + +## 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), + +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" diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..3e89e23 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,35 @@ +// +// CwlCatchException.swift +// CwlAssertionTesting +// +// 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 + +#if SWIFT_PACKAGE +import CwlCatchExceptionSupport +#endif + +private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { + return catchExceptionOfKind(type, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + return catchReturnTypeConverter(self, block: block) + } +} diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m new file mode 100644 index 0000000..8cf414f --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m @@ -0,0 +1,37 @@ +// +// CwlCatchException.m +// CwlAssertionTesting +// +// 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 "CwlCatchException.h" + +#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +__attribute__((visibility("hidden"))) +#endif +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h new file mode 100644 index 0000000..0c8dd87 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h @@ -0,0 +1,32 @@ +// +// CwlCatchException.h +// CwlCatchException +// +// 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 + +//! 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)); diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt new file mode 100644 index 0000000..693a2fe --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift new file mode 100644 index 0000000..8792aac --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift @@ -0,0 +1,19 @@ +import PackageDescription + +let package = Package( + name: "CwlPreconditionTesting", + targets: [ + Target(name: "CwlPreconditionTesting", dependencies: [ + "CwlMachBadInstructionHandler" + ]), + Target(name: "CwlMachBadInstructionHandler") + ], + dependencies: [ + .Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])), + ], + exclude: [ + "Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + ] +) diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a42a5b5 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md @@ -0,0 +1,73 @@ +# CwlPreconditionTesting + +A Mach exception handler, written in Swift and Objective-C, that allows `EXC_BAD_INSTRUCTION` (as raised by Swift's `assertionFailure`/`preconditionFailure`/`fatalError`) to be caught and tested. + +NOTE: the iOS code runs in the simulator *only*. It is for logic testing and cannot be deployed to the device due to the Mach exception API being private on iOS. + +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) + +## 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), + +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/CwlPreconditionTesting.git", majorVersion: 1) + +### CocoaPods + +Add the following lines to your target in your "Podfile": + + pod 'CwlPreconditionTesting', :git => 'https://github.com/mattgallagher/CwlPreconditionTesting.git' + pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git' + +### Carthage + +Add the following line to your Cartfile: + + git "https://github.com/mattgallagher/CwlPreconditionTesting.git" "master" + +## 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) diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m new file mode 100644 index 0000000..8183196 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m @@ -0,0 +1,50 @@ +// +// CwlMachBadExceptionHandler.m +// 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. +// + +#if defined(__x86_64__) + + #import "mach_excServer.h" + #import "CwlMachBadInstructionHandler.h" + + @protocol BadInstructionReply + +(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 diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h new file mode 100644 index 0000000..aef59c2 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -0,0 +1,70 @@ +// +// CwlMachBadInstructionHandler.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 +#import + +NS_ASSUME_NONNULL_BEGIN + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; +} request_mach_exception_raise_t; + +// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; +} reply_mach_exception_raise_state_t; + +typedef struct +{ + mach_port_t exception_port; + exception_type_t exception; + mach_exception_data_type_t const * _Nullable code; + mach_msg_type_number_t codeCnt; + int32_t * _Nullable flavor; + natural_t const * _Nullable old_state; + mach_msg_type_number_t old_stateCnt; + thread_state_t _Nullable new_state; + mach_msg_type_number_t * _Nullable new_stateCnt; +} bad_instruction_exception_reply_t; + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c new file mode 100644 index 0000000..733c564 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Sun Jan 29 19:05:29 2017 + * with a MiG generated by bootstrap_cmds-96.20.2 + * OPTIONS: + */ + +#if defined(__x86_64__) + +/* Module mach_exc */ + +#define __MIG_check__Request__mach_exc_subsystem__ 1 + +#include "mach_excServer.h" + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + + typedef __Request__mach_exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise") + __BeforeRcvRpc(2405, "mach_exception_raise") + +#if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state") + __BeforeRcvRpc(2406, "mach_exception_raise_state") + +#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") + +#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity") +} + + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = { + mach_exc_server_routine, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + OutHeadP->msgh_reserved = 0; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h new file mode 100644 index 0000000..52e53ae --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h @@ -0,0 +1,321 @@ +#ifndef _mach_exc_server_ +#define _mach_exc_server_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +/* BEGIN MIG_STRNCPY_ZEROFILL CODE */ + +#if defined(__has_include) +#if __has_include() +#ifndef USING_MIG_STRNCPY_ZEROFILL +#define USING_MIG_STRNCPY_ZEROFILL +#endif +#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ +#endif /* __has_include() */ +#endif /* __has_include */ + +/* END MIG_STRNCPY_ZEROFILL CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigServerHeader +__BeforeMigServerHeader +#endif /* __BeforeMigServerHeader */ + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +mig_routine_t mach_exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +extern const struct catch_mach_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem; + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + + +/* union of all requests */ + +#ifndef __RequestUnion__catch_mach_exc_subsystem__defined +#define __RequestUnion__catch_mach_exc_subsystem__defined +union __RequestUnion__catch_mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2405 },\ + { "mach_exception_raise_state", 2406 },\ + { "mach_exception_raise_state_identity", 2407 } +#endif + +#ifdef __AfterMigServerHeader +__AfterMigServerHeader +#endif /* __AfterMigServerHeader */ + +#endif /* _mach_exc_server_ */ diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..91e5d4d --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,89 @@ +// +// CwlBadInstructionException.swift +// 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 + +#if SWIFT_PACKAGE + import CwlMachBadInstructionHandler +#endif + +private func raiseBadInstructionException() { + BadInstructionException().raise() +} + +/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type. +@objc(BadInstructionException) +public class BadInstructionException: NSException { + static var name: String = "com.cocoawithlove.BadInstruction" + + init() { + super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// 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 = 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 = 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.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 + } +} diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..f96ec63 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,197 @@ +// +// CwlCatchBadInstruction.swift +// 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 + +#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) + } + } + + extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> 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(in block: (UnsafeMutablePointer) -> 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() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil + + static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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.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.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 + } + + /// 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) + } + } + + 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 + diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift new file mode 100644 index 0000000..eb9bc19 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift @@ -0,0 +1,108 @@ +// +// 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.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 diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..8d99d5e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,55 @@ +// +// CwlDarwinDefinitions.swift +// 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 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.size / MemoryLayout.size) + + public let EXC_TYPES_COUNT = 14 + public struct execTypesCountTuple { + // 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 diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h new file mode 100644 index 0000000..7c50da1 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h @@ -0,0 +1,32 @@ +// +// 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 + +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" diff --git a/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h new file mode 100644 index 0000000..4e28f95 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h @@ -0,0 +1,29 @@ +// +// 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 + +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[]; diff --git a/Carthage/Checkouts/Nimble/Dockerfile.test b/Carthage/Checkouts/Nimble/Dockerfile.test new file mode 100644 index 0000000..a995ae2 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Dockerfile.test @@ -0,0 +1,3 @@ +FROM swift:latest +COPY . . +CMD ./test swiftpm diff --git a/Carthage/Checkouts/Nimble/Gemfile b/Carthage/Checkouts/Nimble/Gemfile new file mode 100644 index 0000000..eca9219 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.5.0' diff --git a/Carthage/Checkouts/Nimble/Gemfile.lock b/Carthage/Checkouts/Nimble/Gemfile.lock new file mode 100644 index 0000000..36a0839 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Gemfile.lock @@ -0,0 +1,76 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + atomos (0.1.2) + claide (1.0.2) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + minitest (5.11.3) + molinillo (0.6.5) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + ruby-macho (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.5.0) + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Nimble/LICENSE b/Carthage/Checkouts/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/Nimble/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Nimble/Nimble.podspec b/Carthage/Checkouts/Nimble/Nimble.podspec new file mode 100644 index 0000000..a42913f --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.podspec @@ -0,0 +1,52 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "7.3.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. + DESC + 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.osx.deployment_target = "10.10" + s.tvos.deployment_target = "9.0" + s.source = { :git => "https://github.com/Quick/Nimble.git", + :tag => "v#{s.version}" } + + s.source_files = [ + "Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlCatchException/Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/**/*.{swift,h,m,c}", + ] + + s.osx.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.ios.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.tvos.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", + ] + + s.exclude_files = "Sources/Nimble/Adapters/NonObjectiveC/*.swift" + s.weak_framework = "XCTest" + s.requires_arc = true + s.compiler_flags = '-DPRODUCT_NAME=Nimble/Nimble' + s.pod_target_xcconfig = { + 'APPLICATION_EXTENSION_API_ONLY' => 'YES', + 'ENABLE_BITCODE' => 'NO', + 'OTHER_LDFLAGS' => '$(inherited) -weak-lswiftXCTest -Xlinker -no_application_extension', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..70c2221 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2371 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + A8F2B2541E79A4AB005BDD17 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + A8F2B2581E79A4B0005BDD17 /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 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 */; }; + 1F0648D51963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; }; + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E41CA89FB600A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; }; + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871E71CA8A18400A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; }; + 1F1871E81CA8A18400A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; }; + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F1A74291940169200FFFC47 /* Nimble.framework */; }; + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 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 */; }; + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A56671A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; }; + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; }; + 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 */; }; + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F5DF1931BDCA10200C3A531 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; }; + 1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; }; + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; }; + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + 1F5DF1AA1BDCA10200C3A531 /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F925EAD195C0D6300ED456B /* Nimble.framework */; }; + 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F925EE2195C0DFD00ED456B /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFD195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD6A1968AB07008ED995 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; }; + 1FD8CD6B1968AB07008ED995 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; }; + 1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 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 */; }; + 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 */; }; + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C41E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.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 */; }; + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + CD79C9A51D2CC848004B6F9A /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + CD79C9A71D2CC848004B6F9A /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + CD79C9AF1D2CC848004B6F9A /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; }; + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 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 */; }; + 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 */; }; + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; }; + 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, ); }; }; + CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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 */; }; + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F5DF1541BDCA0CE00C3A531; + remoteInfo = "Nimble-tvOS"; + }; + 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = ""; }; + 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTest.swift; sourceTree = ""; }; + 1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = ""; }; + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSL.h; sourceTree = ""; }; + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSL.m; sourceTree = ""; }; + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBExceptionCapture.h; sourceTree = ""; }; + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBExceptionCapture.m; sourceTree = ""; }; + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBStringify.h; sourceTree = ""; }; + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBStringify.m; sourceTree = ""; }; + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBExpectation.swift; sourceTree = ""; }; + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBObjCMatcher.swift; sourceTree = ""; }; + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionCapture.swift; sourceTree = ""; }; + 1F1871E31CA89FB600A34BF2 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = ""; }; + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherFunc.swift; sourceTree = ""; }; + 1F1A74291940169200FFFC47 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A742D1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1A742E1940169200FFFC47 /* Nimble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nimble.h; sourceTree = ""; }; + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A743A1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAKindOfTest.swift; sourceTree = ""; }; + 1F2752D119445B8400052A26 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = README.md; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.markdown; }; + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmptyTest.swift; sourceTree = ""; }; + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAsyncTest.m; sourceTree = ""; }; + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NimbleSpecHelper.h; sourceTree = ""; }; + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeAnInstanceOfTest.m; sourceTree = ""; }; + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeKindOfTest.m; sourceTree = ""; }; + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeCloseToTest.m; sourceTree = ""; }; + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeginWithTest.m; sourceTree = ""; }; + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanTest.m; sourceTree = ""; }; + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeIdenticalToTest.m; sourceTree = ""; }; + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanTest.m; sourceTree = ""; }; + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTruthyTest.m; sourceTree = ""; }; + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalsyTest.m; sourceTree = ""; }; + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTrueTest.m; sourceTree = ""; }; + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalseTest.m; sourceTree = ""; }; + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeNilTest.m; sourceTree = ""; }; + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainTest.m; sourceTree = ""; }; + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEndWithTest.m; sourceTree = ""; }; + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEqualTest.m; sourceTree = ""; }; + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCMatchTest.m; sourceTree = ""; }; + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCRaiseExceptionTest.m; sourceTree = ""; }; + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertionTest.swift; sourceTree = ""; }; + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSyncTest.m; sourceTree = ""; }; + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoidTest.swift; sourceTree = ""; }; + 1F91DD301C74BF61002C309F /* BeVoid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoid.swift; sourceTree = ""; }; + 1F925EAD195C0D6300ED456B /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousTest.swift; sourceTree = ""; }; + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOfTest.swift; sourceTree = ""; }; + 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaisesExceptionTest.swift; sourceTree = ""; }; + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLogicalTest.swift; sourceTree = ""; }; + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseToTest.swift; sourceTree = ""; }; + 1F925EF8195C175000ED456B /* BeNilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeNilTest.swift; sourceTree = ""; }; + 1F925EFB195C186800ED456B /* BeginWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeginWithTest.swift; sourceTree = ""; }; + 1F925EFE195C187600ED456B /* EndWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWithTest.swift; sourceTree = ""; }; + 1F925F01195C189500ED456B /* ContainTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainTest.swift; sourceTree = ""; }; + 1F925F04195C18B700ED456B /* EqualTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EqualTest.swift; sourceTree = ""; }; + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanTest.swift; sourceTree = ""; }; + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanTest.swift; sourceTree = ""; }; + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanOrEqualToTest.swift; sourceTree = ""; }; + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanOrEqualToTest.swift; sourceTree = ""; }; + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeEmptyTest.m; sourceTree = ""; }; + 1FA0C3FE1E30B14500623165 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToTest.swift; sourceTree = ""; }; + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleEnvironment.swift; sourceTree = ""; }; + 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotificationTest.swift; sourceTree = ""; }; + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotification.swift; sourceTree = ""; }; + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionRecorder.swift; sourceTree = ""; }; + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdapterProtocols.swift; sourceTree = ""; }; + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleXCTestHandler.swift; sourceTree = ""; }; + 1FD8CD081968AB07008ED995 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + 1FD8CD091968AB07008ED995 /* Expectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expectation.swift; sourceTree = ""; }; + 1FD8CD0A1968AB07008ED995 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailureMessage.swift; sourceTree = ""; }; + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOf.swift; sourceTree = ""; }; + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeAKindOf.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseTo.swift; sourceTree = ""; }; + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmpty.swift; sourceTree = ""; }; + 1FD8CD111968AB07008ED995 /* BeginWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeginWith.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThanOrEqualTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeIdenticalTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThanOrEqual.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD171968AB07008ED995 /* BeLogical.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLogical.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD181968AB07008ED995 /* BeNil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeNil.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1A1968AB07008ED995 /* Contain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Contain.swift; sourceTree = ""; }; + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWith.swift; sourceTree = ""; }; + 1FD8CD1C1968AB07008ED995 /* Equal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Equal.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = ""; }; + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = ""; }; + 1FD8CD261968AB07008ED995 /* Await.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Await.swift; sourceTree = ""; }; + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = ""; }; + 1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = ""; }; + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionDispatcher.swift; sourceTree = ""; }; + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpectationMessage.swift; sourceTree = ""; }; + 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowErrorTest.swift; sourceTree = ""; }; + 29EA59651B551EE6002D767E /* ThrowError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowError.swift; sourceTree = ""; }; + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseProvider.swift; sourceTree = ""; }; + 472FD1341B9E085700C7B8DA /* HaveCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCount.swift; sourceTree = ""; }; + 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCountTest.swift; sourceTree = ""; }; + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCountTest.m; sourceTree = ""; }; + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = ""; }; + 7A0A26221E7F52360092A34E /* ToSucceed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceed.swift; sourceTree = ""; }; + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceedTest.swift; sourceTree = ""; }; + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfying.swift; sourceTree = ""; }; + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfyingTest.m; sourceTree = ""; }; + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfyingTest.swift; sourceTree = ""; }; + 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOfTest.swift; sourceTree = ""; }; + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOf.swift; sourceTree = ""; }; + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAnyOfTest.m; sourceTree = ""; }; + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcStringersTest.m; sourceTree = ""; }; + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertion.swift; sourceTree = ""; }; + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCUserDescriptionTest.m; sourceTree = ""; }; + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDescriptionTest.swift; sourceTree = ""; }; + A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAllOfTest.swift; sourceTree = ""; }; + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAllOfTest.m; sourceTree = ""; }; + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatisfyAllOf.swift; sourceTree = ""; }; + AE4BA9AC1C88DDB500B73906 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchError.swift; sourceTree = ""; }; + AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = ""; }; + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = ""; }; + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = ""; }; + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = ""; }; + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = ""; }; + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_excServer.h; sourceTree = ""; }; + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DSL+Wait.swift"; sourceTree = ""; }; + DD72EC631A93874A002F7651 /* AllPassTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPassTest.swift; sourceTree = ""; }; + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToObjectTest.swift; sourceTree = ""; }; + DDB1BC781A92235600F743C3 /* AllPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPass.swift; sourceTree = ""; }; + DDB4D5EC19FE43C200E9D9FE /* Match.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Match.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchTest.swift; sourceTree = ""; }; + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAllPassTest.m; sourceTree = ""; }; + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+Register.m"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F1A74251940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74311940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA9195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB4195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F14FB61194180A7009F2A08 /* Helpers */ = { + isa = PBXGroup; + children = ( + 1F14FB63194180C5009F2A08 /* utils.swift */, + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */, + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */, + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */, + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */, + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */, + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */, + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */, + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */, + ); + name = NimbleObjectiveC; + path = Sources/NimbleObjectiveC; + sourceTree = ""; + }; + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */, + ); + path = NonObjectiveC; + sourceTree = ""; + }; + 1F1A741F1940169200FFFC47 = { + isa = PBXGroup; + children = ( + 1F2752D119445B8400052A26 /* README.md */, + 1F1A742B1940169200FFFC47 /* Nimble */, + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */, + 1F1A74381940169200FFFC47 /* NimbleTests */, + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */, + 1F1A742A1940169200FFFC47 /* Products */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + usesTabs = 0; + }; + 1F1A742A1940169200FFFC47 /* Products */ = { + isa = PBXGroup; + children = ( + 1F1A74291940169200FFFC47 /* Nimble.framework */, + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */, + 1F925EAD195C0D6300ED456B /* Nimble.framework */, + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */, + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */, + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 1F1A742B1940169200FFFC47 /* Nimble */ = { + isa = PBXGroup; + children = ( + 1FD8CD041968AB07008ED995 /* Adapters */, + 1FD8CD081968AB07008ED995 /* DSL.swift */, + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */, + 1FD8CD091968AB07008ED995 /* Expectation.swift */, + 1FD8CD0A1968AB07008ED995 /* Expression.swift */, + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */, + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */, + 1F1A742D1940169200FFFC47 /* Info.plist */, + 1FD8CD0C1968AB07008ED995 /* Matchers */, + 1F1A742E1940169200FFFC47 /* Nimble.h */, + 1FD8CD241968AB07008ED995 /* Utils */, + ); + name = Nimble; + path = Sources/Nimble; + sourceTree = ""; + }; + 1F1A74381940169200FFFC47 /* NimbleTests */ = { + isa = PBXGroup; + children = ( + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */, + 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */, + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */, + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */, + 1FFD729A1963FC8200CD29A2 /* objc */, + 1F14FB61194180A7009F2A08 /* Helpers */, + 1F925EE3195C11B000ED456B /* Matchers */, + 1F1A74391940169200FFFC47 /* Supporting Files */, + ); + name = NimbleTests; + path = Tests/NimbleTests; + sourceTree = ""; + }; + 1F1A74391940169200FFFC47 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 1F1A743A1940169200FFFC47 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1F925EE3195C11B000ED456B /* Matchers */ = { + isa = PBXGroup; + children = ( + DD72EC631A93874A002F7651 /* AllPassTest.swift */, + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */, + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */, + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */, + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */, + 1F925EFB195C186800ED456B /* BeginWithTest.swift */, + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */, + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */, + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */, + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */, + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */, + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */, + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */, + 1F925EF8195C175000ED456B /* BeNilTest.swift */, + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */, + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */, + 1F925F01195C189500ED456B /* ContainTest.swift */, + 1F925EFE195C187600ED456B /* EndWithTest.swift */, + 1F925F04195C18B700ED456B /* EqualTest.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 */, + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */, + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD041968AB07008ED995 /* Adapters */ = { + isa = PBXGroup; + children = ( + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */, + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */, + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */, + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */, + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */, + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */, + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */, + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */, + ); + path = Adapters; + sourceTree = ""; + }; + 1FD8CD0C1968AB07008ED995 /* Matchers */ = { + isa = PBXGroup; + children = ( + DDB1BC781A92235600F743C3 /* AllPass.swift */, + 1F1871E31CA89FB600A34BF2 /* Async.swift */, + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */, + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */, + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */, + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */, + 1FD8CD111968AB07008ED995 /* BeginWith.swift */, + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */, + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */, + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */, + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */, + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */, + 1FD8CD171968AB07008ED995 /* BeLogical.swift */, + 1FD8CD181968AB07008ED995 /* BeNil.swift */, + 1F91DD301C74BF61002C309F /* BeVoid.swift */, + 1FD8CD1A1968AB07008ED995 /* Contain.swift */, + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */, + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */, + 1FD8CD1C1968AB07008ED995 /* Equal.swift */, + 472FD1341B9E085700C7B8DA /* HaveCount.swift */, + DDB4D5EC19FE43C200E9D9FE /* Match.swift */, + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */, + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */, + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */, + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */, + 1FA0C3FE1E30B14500623165 /* Predicate.swift */, + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */, + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */, + 29EA59651B551EE6002D767E /* ThrowError.swift */, + 7A0A26221E7F52360092A34E /* ToSucceed.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD241968AB07008ED995 /* Utils */ = { + isa = PBXGroup; + children = ( + 1FD8CD251968AB07008ED995 /* Functional.swift */, + 1FD8CD261968AB07008ED995 /* Await.swift */, + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */, + 1FD8CD281968AB07008ED995 /* Stringers.swift */, + AE4BA9AC1C88DDB500B73906 /* Errors.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 1FFD729A1963FC8200CD29A2 /* objc */ = { + isa = PBXGroup; + children = ( + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */, + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */, + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */, + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */, + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */, + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */, + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */, + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */, + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */, + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */, + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */, + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */, + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */, + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */, + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */, + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */, + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */, + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */, + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = { + isa = PBXGroup; + children = ( + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */, + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */, + ); + name = "Carthage-Checkouts"; + path = Carthage/Checkouts; + sourceTree = ""; + }; + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */, + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */, + ); + name = CwlCatchException; + path = CwlCatchException/Sources; + sourceTree = ""; + }; + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */, + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */, + ); + name = CwlPreconditionTesting; + path = CwlPreconditionTesting/Sources; + sourceTree = ""; + }; + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */, + ); + path = CwlCatchException; + sourceTree = ""; + }; + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */ = { + isa = PBXGroup; + children = ( + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */, + CDFB6A211F7E07C600AD8CC7 /* include */, + ); + path = CwlCatchExceptionSupport; + sourceTree = ""; + }; + CDFB6A211F7E07C600AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */, + ); + path = include; + sourceTree = ""; + }; + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */, + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */, + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */, + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */, + CDFB6A2F1F7E082400AD8CC7 /* Mach */, + CDFB6A311F7E082400AD8CC7 /* Posix */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; + CDFB6A2F1F7E082400AD8CC7 /* Mach */ = { + isa = PBXGroup; + children = ( + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */, + ); + path = Mach; + sourceTree = ""; + }; + CDFB6A311F7E082400AD8CC7 /* Posix */ = { + isa = PBXGroup; + children = ( + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */, + ); + path = Posix; + sourceTree = ""; + }; + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = { + isa = PBXGroup; + children = ( + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */, + CDFB6A351F7E082400AD8CC7 /* include */, + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */, + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */, + ); + path = CwlMachBadInstructionHandler; + sourceTree = ""; + }; + CDFB6A351F7E082400AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */, + ); + path = include; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + 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 */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + 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; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F1A74281940169200FFFC47 /* Nimble-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */; + buildPhases = ( + 1F1A74241940169200FFFC47 /* Sources */, + 1F1A74251940169200FFFC47 /* Frameworks */, + 1F1A74261940169200FFFC47 /* Headers */, + 1F1A74271940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-iOS"; + productName = "Nimble-iOS"; + productReference = 1F1A74291940169200FFFC47 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */; + buildPhases = ( + 1F1A74301940169200FFFC47 /* Sources */, + 1F1A74311940169200FFFC47 /* Frameworks */, + 1F1A74321940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F1A74371940169200FFFC47 /* PBXTargetDependency */, + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */, + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */, + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */, + ); + name = "Nimble-iOSTests"; + productName = "Nimble-iOSTests"; + productReference = 1F1A74341940169200FFFC47 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */; + buildPhases = ( + 1F5DF1501BDCA0CE00C3A531 /* Sources */, + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */, + 1F5DF1521BDCA0CE00C3A531 /* Headers */, + 1F5DF1531BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-tvOS"; + productName = "Nimble-tvOS"; + productReference = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */; + buildPhases = ( + 1F5DF15A1BDCA0CE00C3A531 /* Sources */, + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */, + 1F5DF15C1BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */, + ); + name = "Nimble-tvOSTests"; + productName = "Nimble-tvOSTests"; + productReference = 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F925EAC195C0D6300ED456B /* Nimble-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */; + buildPhases = ( + 1F925EA8195C0D6300ED456B /* Sources */, + 1F925EA9195C0D6300ED456B /* Frameworks */, + 1F925EAA195C0D6300ED456B /* Headers */, + 1F925EAB195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-macOS"; + productName = "Nimble-macOS"; + productReference = 1F925EAD195C0D6300ED456B /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */; + buildPhases = ( + 1F925EB3195C0D6300ED456B /* Sources */, + 1F925EB4195C0D6300ED456B /* Frameworks */, + 1F925EB5195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */, + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */, + ); + name = "Nimble-macOSTests"; + productName = "Nimble-OSXTests"; + productReference = 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1F1A74201940169200FFFC47 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F925EAC195C0D6300ED456B; + }; + A8F2B2541E79A4AB005BDD17 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1F1A741F1940169200FFFC47; + productRefGroup = 1F1A742A1940169200FFFC47 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1F925EAC195C0D6300ED456B /* Nimble-macOS */, + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */, + 1F1A74281940169200FFFC47 /* Nimble-iOS */, + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */, + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */, + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */, + A8F2B2541E79A4AB005BDD17 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F1A74271940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74321940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1531BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15C1BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAB195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB5195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A8F2B2581E79A4B0005BDD17 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F1A74241940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */, + 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 */, + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */, + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */, + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */, + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */, + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */, + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 29EA59661B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */, + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */, + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */, + CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */, + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871E41CA89FB600A34BF2 /* Async.swift in Sources */, + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */, + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Await.swift in Sources */, + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, + CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */, + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74301940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */, + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */, + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */, + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */, + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */, + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */, + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + 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 */, + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0A1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13B1B9E0CFE00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1501BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */, + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */, + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */, + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */, + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E81CA8A18400A34BF2 /* Async.swift in Sources */, + 1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */, + 1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */, + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */, + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */, + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */, + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */, + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */, + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */, + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */, + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */, + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */, + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */, + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */, + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */, + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */, + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */, + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */, + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */, + 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 */, + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */, + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */, + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */, + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */, + CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, + 1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */, + 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15A1BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */, + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */, + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */, + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */, + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */, + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */, + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */, + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */, + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */, + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */, + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */, + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */, + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */, + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */, + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */, + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */, + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */, + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */, + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */, + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */, + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */, + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */, + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */, + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */, + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */, + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */, + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */, + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */, + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */, + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */, + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 1F5DF1931BDCA10200C3A531 /* SynchronousTest.swift in Sources */, + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */, + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */, + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */, + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */, + 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 */, + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */, + CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */, + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 6CAEDD0C1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */, + CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */, + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */, + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */, + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */, + CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */, + CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA8195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */, + 1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */, + 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 */, + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */, + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */, + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */, + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */, + 29EA59671B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */, + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */, + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */, + CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */, + CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */, + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */, + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Await.swift in Sources */, + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, + CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */, + 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB3195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.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 */, + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAC19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + 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 */, + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59641B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0B1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13A1B9E0A9F00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1F1A74371940169200FFFC47 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */; + }; + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */; + targetProxy = 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */; + }; + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */; + }; + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */; + }; + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F1A743D1940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1F1A743E1940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 1F1A74401940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + "$(inherited)", + ); + 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; + 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; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74411940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + ); + 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"; + 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; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 1F1A74431940169200FFFC47 /* Debug */ = { + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_CODE_SIGN_FLAGS = "--verbose"; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74441940169200FFFC47 /* Release */ = { + 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"; + 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"; + }; + name = Release; + }; + 1F5DF1661BDCA0CE00C3A531 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/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; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 1F5DF1671BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + 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 = ( + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F5DF1681BDCA0CE00C3A531 /* Debug */ = { + 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"; + 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; + }; + name = Debug; + }; + 1F5DF1691BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + 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"; + 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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F925EC1195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + 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"; + 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 = { + 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)", + "$(inherited)", + ); + 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"; + 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; + }; + name = Release; + }; + 1F925EC4195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F925EC5195C0D6300ED456B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + A8F2B2551E79A4AB005BDD17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Debug; + }; + A8F2B2561E79A4AB005BDD17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A743D1940169200FFFC47 /* Debug */, + 1F1A743E1940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74401940169200FFFC47 /* Debug */, + 1F1A74411940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74431940169200FFFC47 /* Debug */, + 1F1A74441940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1661BDCA0CE00C3A531 /* Debug */, + 1F5DF1671BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1681BDCA0CE00C3A531 /* Debug */, + 1F5DF1691BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC1195C0D6300ED456B /* Debug */, + 1F925EC2195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC4195C0D6300ED456B /* Debug */, + 1F925EC5195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8F2B2551E79A4AB005BDD17 /* Debug */, + A8F2B2561E79A4AB005BDD17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F1A74201940169200FFFC47 /* Project object */; +} diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..80405c9 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..d640838 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..c45d780 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Nimble/Package.swift b/Carthage/Checkouts/Nimble/Package.swift new file mode 100644 index 0000000..8d0b745 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:3.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/Nimble/Package@swift-4.swift b/Carthage/Checkouts/Nimble/Package@swift-4.swift new file mode 100644 index 0000000..740b842 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Package@swift-4.swift @@ -0,0 +1,22 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + products: [ + .library(name: "Nimble", targets: ["Nimble"]), + ], + targets: [ + .target( + name: "Nimble", + dependencies: [] + ), + .testTarget( + name: "NimbleTests", + dependencies: ["Nimble"], + exclude: ["objc"] + ), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Nimble/README.md b/Carthage/Checkouts/Nimble/README.md new file mode 100644 index 0000000..19c562f --- /dev/null +++ b/Carthage/Checkouts/Nimble/README.md @@ -0,0 +1,1764 @@ +# Nimble + +[![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) +[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble) + +Use Nimble to express the expected outcomes of Swift +or Objective-C expressions. Inspired by +[Cedar](https://github.com/pivotal/cedar). + +```swift +// Swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + +# How to Use Nimble + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest) +- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto) + - [Custom Failure Messages](#custom-failure-messages) + - [Type Safety](#type-safety) + - [Operator Overloads](#operator-overloads) + - [Lazily Computed Values](#lazily-computed-values) + - [C Primitives](#c-primitives) + - [Asynchronous Expectations](#asynchronous-expectations) + - [Objective-C Support](#objective-c-support) + - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand) +- [Built-in Matcher Functions](#built-in-matcher-functions) + - [Type Checking](#type-checking) + - [Equivalence](#equivalence) + - [Identity](#identity) + - [Comparisons](#comparisons) + - [Types/Classes](#typesclasses) + - [Truthiness](#truthiness) + - [Swift Assertions](#swift-assertions) + - [Swift Error Handling](#swift-error-handling) + - [Exceptions](#exceptions) + - [Collection Membership](#collection-membership) + - [Strings](#strings) + - [Collection Elements](#collection-elements) + - [Collection Count](#collection-count) + - [Notifications](#notifications) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) + - [Custom Validation](#custom-validation) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [PredicateResult](#predicateresult) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Basic Customization](#basic-customization) + - [Full Customization](#full-customization) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) + - [Migrating from the Old Matcher API](#migrating-from-the-old-matcher-api) + - [Minimal Step - Use `.predicate`](#minimal-step---use-predicate) + - [Convert to use `Predicate` Type with Old Matcher Constructor](#convert-to-use-predicate-type-with-old-matcher-constructor) + - [Convert to `Predicate` Type with Preferred Constructor](#convert-to-predicate-type-with-preferred-constructor) + - [Deprecation Roadmap](#deprecation-roadmap) +- [Installing Nimble](#installing-nimble) + - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule) + - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods) + - [Using Nimble without XCTest](#using-nimble-without-xctest) + + + +# Some Background: Expressing Outcomes Using Assertions in XCTest + +Apple's Xcode includes the XCTest framework, which provides +assertion macros to test whether code behaves properly. +For example, to assert that `1 + 1 = 2`, XCTest has you write: + +```swift +// Swift + +XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two") +``` + +Or, in Objective-C: + +```objc +// Objective-C + +XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two"); +``` + +XCTest assertions have a couple of drawbacks: + +1. **Not enough macros.** There's no easy way to assert that a string + contains a particular substring, or that a number is less than or + equal to another. +2. **It's hard to write asynchronous tests.** XCTest forces you to write + a lot of boilerplate code. + +Nimble addresses these concerns. + +# Nimble: Expectations Using `expect(...).to` + +Nimble allows you to express expectations using a natural, +easily understood language: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).to(equal("Squee!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).to(equal(@"Squee!")); +``` + +> The `expect` function autocompletes to include `file:` and `line:`, + but these parameters are optional. Use the default values to have + Xcode highlight the correct line when an expectation is not met. + +To perform the opposite expectation--to assert something is *not* +equal--use `toNot` or `notTo`: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).toNot(equal("Oh, hello there!")) +expect(seagull.squawk).notTo(equal("Oh, hello there!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).toNot(equal(@"Oh, hello there!")); +expect(seagull.squawk).notTo(equal(@"Oh, hello there!")); +``` + +## Custom Failure Messages + +Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text: + +```swift +// Swift + +expect(1 + 1).to(equal(3)) +// failed - expected to equal <3>, got <2> + +expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded") +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3>, got <2> +``` + +Or the *WithDescription version in Objective-C: + +```objc +// Objective-C + +@import Nimble; + +expect(@(1+1)).to(equal(@3)); +// failed - expected to equal <3.0000>, got <2.0000> + +expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded"); +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3.0000>, got <2.0000> +``` + +## Type Safety + +Nimble makes sure you don't compare two types that don't match: + +```swift +// Swift + +// Does not compile: +expect(1 + 1).to(equal("Squee!")) +``` + +> Nimble uses generics--only available in Swift--to ensure + type correctness. That means type checking is + not available when using Nimble in Objective-C. :sob: + +## Operator Overloads + +Tired of so much typing? With Nimble, you can use overloaded operators +like `==` for equivalence, or `>` for comparisons: + +```swift +// Swift + +// Passes if squawk does not equal "Hi!": +expect(seagull.squawk) != "Hi!" + +// Passes if 10 is greater than 2: +expect(10) > 2 +``` + +> Operator overloads are only available in Swift, so you won't be able + to use this syntax in Objective-C. :broken_heart: + +## Lazily Computed Values + +The `expect` function doesn't evaluate the value it's given until it's +time to match. So Nimble can test whether an expression raises an +exception once evaluated: + +```swift +// Swift + +// Note: Swift currently doesn't have exceptions. +// Only Objective-C code can raise exceptions +// that Nimble will catch. +// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064) +let exception = NSException( + name: NSInternalInconsistencyException, + reason: "Not enough fish in the sea.", + userInfo: ["something": "is fishy"]) +expect { exception.raise() }.to(raiseException()) + +// Also, you can customize raiseException to be more specific +expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException)) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea")) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea", + userInfo: ["something": "is fishy"])) +``` + +Objective-C works the same way, but you must use the `expectAction` +macro when making an expectation on an expression that has no return +value: + +```objc +// Objective-C + +NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Not enough fish in the sea." + userInfo:nil]; +expectAction(^{ [exception raise]; }).to(raiseException()); + +// Use the property-block syntax to be more specific. +expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException)); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea")); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea"). + userInfo(@{@"something": @"is fishy"})); + +// You can also pass a block for custom matching of the raised exception +expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(NSInternalInconsistencyException)); +})); +``` + +## C Primitives + +Some testing frameworks make it hard to test primitive C values. +In Nimble, it just works: + +```swift +// Swift + +let actual: CInt = 1 +let expectedValue: CInt = 1 +expect(actual).to(equal(expectedValue)) +``` + +In fact, Nimble uses type inference, so you can write the above +without explicitly specifying both types: + +```swift +// Swift + +expect(1 as CInt).to(equal(1)) +``` + +> In Objective-C, Nimble only supports Objective-C objects. To + make expectations on primitive C values, wrap then in an object + literal: + +```objc +expect(@(1 + 1)).to(equal(@2)); +``` + +## Asynchronous Expectations + +In Nimble, it's easy to make expectations on values that are updated +asynchronously. Just use `toEventually` or `toEventuallyNot`: + +```swift +// Swift 3.0 and later + +DispatchQueue.main.async { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```swift +// Swift 2.3 and earlier + +dispatch_async(dispatch_get_main_queue()) { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```objc +// Objective-C + +dispatch_async(dispatch_get_main_queue(), ^{ + [ocean add:@"dolphins"]; + [ocean add:@"whales"]; +}); +expect(ocean).toEventually(contain(@"dolphins", @"whales")); +``` + +Note: toEventually triggers its polls on the main thread. Blocking the main +thread will cause Nimble to stop the run loop. This can cause test pollution +for whatever incomplete code that was running on the main thread. Blocking the +main thread can be caused by blocking IO, calls to sleep(), deadlocks, and +synchronous IPC. + +In the above example, `ocean` is constantly re-evaluated. If it ever +contains dolphins and whales, the expectation passes. If `ocean` still +doesn't contain them, even after being continuously re-evaluated for one +whole second, the expectation fails. + +Sometimes it takes more than a second for a value to update. In those +cases, use the `timeout` parameter: + +```swift +// Swift + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).toEventually(contain("starfish"), timeout: 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) +``` + +```objc +// Objective-C + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).withTimeout(3).toEventually(contain(@"starfish")); +``` + +You can also provide a callback by using the `waitUntil` function: + +```swift +// Swift + +waitUntil { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +Note: `waitUntil` triggers its timeout code on the main thread. Blocking the main +thread will cause Nimble to stop the run loop to continue. This can cause test +pollution for whatever incomplete code that was running on the main thread. +Blocking the main thread can be caused by blocking IO, calls to sleep(), +deadlocks, and synchronous IPC. + +In some cases (e.g. when running on slower machines) it can be useful to modify +the default timeout and poll interval values. This can be done as follows: + +```swift +// Swift + +// Increase the global timeout to 5 seconds: +Nimble.AsyncDefaults.Timeout = 5 + +// Slow the polling interval to 0.1 seconds: +Nimble.AsyncDefaults.PollInterval = 0.1 +``` + +## Objective-C Support + +Nimble has full support for Objective-C. However, there are two things +to keep in mind when using Nimble in Objective-C: + +1. All parameters passed to the `expect` function, as well as matcher + functions like `equal`, must be Objective-C objects or can be converted into + an `NSObject` equivalent: + + ```objc + // Objective-C + + @import Nimble; + + expect(@(1 + 1)).to(equal(@2)); + expect(@"Hello world").to(contain(@"world")); + + // Boxed as NSNumber * + expect(2).to(equal(2)); + expect(1.2).to(beLessThan(2.0)); + expect(true).to(beTruthy()); + + // Boxed as NSString * + expect("Hello world").to(equal("Hello world")); + + // Boxed as NSRange + expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10))); + ``` + +2. To make an expectation on an expression that does not return a value, + such as `-[NSException raise]`, use `expectAction` instead of + `expect`: + + ```objc + // Objective-C + + expectAction(^{ [exception raise]; }).to(raiseException()); + ``` + +The following types are currently converted to an `NSObject` type: + + - **C Numeric types** are converted to `NSNumber *` + - `NSRange` is converted to `NSValue *` + - `char *` is converted to `NSString *` + +For the following matchers: + +- `equal` +- `beGreaterThan` +- `beGreaterThanOrEqual` +- `beLessThan` +- `beLessThanOrEqual` +- `beCloseTo` +- `beTrue` +- `beFalse` +- `beTruthy` +- `beFalsy` +- `haveCount` + +If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues). + +## Disabling Objective-C Shorthand + +Nimble provides a shorthand for expressing expectations using the +`expect` function. To disable this shorthand in Objective-C, define the +`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before +importing Nimble: + +```objc +#define NIMBLE_DISABLE_SHORT_SYNTAX 1 + +@import Nimble; + +NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!")); +``` + +> Disabling the shorthand is useful if you're testing functions with + names that conflict with Nimble functions, such as `expect` or + `equal`. If that's not the case, there's no point in disabling the + shorthand. + +# Built-in Matcher Functions + +Nimble includes a wide variety of matcher functions. + +## Type Checking + +Nimble supports checking the type membership of any kind of object, whether +Objective-C conformant or not: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// The following tests pass +expect(1).to(beAKindOf(Int.self)) +expect("turtle").to(beAKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beAKindOf(SomeProtocol.self)) +expect(classObject).to(beAKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beAKindOf(SomeProtocol.self)) +expect(structObject).to(beAKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAKindOf(SomeClassConformingToProtocol.self)) +``` + +```objc +// Objective-C + +// The following tests pass +NSMutableArray *array = [NSMutableArray array]; +expect(array).to(beAKindOf([NSArray class])); +expect(@1).toNot(beAKindOf([NSNull class])); +``` + +Objects can be tested for their exact types using the `beAnInstanceOf` matcher: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only +// passes if the object is the EXACT type requested. The following +// tests pass -- note its behavior when working in an inheritance hierarchy. +expect(1).to(beAnInstanceOf(Int.self)) +expect("turtle").to(beAnInstanceOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self)) +``` + +## Equivalence + +```swift +// Swift + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) +expect(actual) == expected + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +expect(actual) != expected +``` + +```objc +// Objective-C + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +``` + +Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`. +`equal` will always fail when used to compare one or more `nil` values. + +## Identity + +```swift +// Swift + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)) +expect(actual) === expected + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)) +expect(actual) !== expected +``` + +It is important to remember that `beIdenticalTo` only makes sense when comparing +types with reference semantics, which have a notion of identity. In Swift, +that means types that are defined as a `class`. + +This matcher will not work when comparing types with value semantics such as +those defined as a `struct` or `enum`. If you need to compare two value types, +consider what it means for instances of your type to be identical. This may mean +comparing individual properties or, if it makes sense to do so, conforming your type +to `Equatable` and using Nimble's equivalence matchers instead. + + +```objc +// Objective-C + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)); + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)); +``` + +## Comparisons + +```swift +// Swift + +expect(actual).to(beLessThan(expected)) +expect(actual) < expected + +expect(actual).to(beLessThanOrEqualTo(expected)) +expect(actual) <= expected + +expect(actual).to(beGreaterThan(expected)) +expect(actual) > expected + +expect(actual).to(beGreaterThanOrEqualTo(expected)) +expect(actual) >= expected +``` + +```objc +// Objective-C + +expect(actual).to(beLessThan(expected)); +expect(actual).to(beLessThanOrEqualTo(expected)); +expect(actual).to(beGreaterThan(expected)); +expect(actual).to(beGreaterThanOrEqualTo(expected)); +``` + +> Values given to the comparison matchers above must implement + `Comparable`. + +Because of how computers represent floating point numbers, assertions +that two floating point numbers be equal will sometimes fail. To express +that two numbers should be close to one another within a certain margin +of error, use `beCloseTo`: + +```swift +// Swift + +expect(actual).to(beCloseTo(expected, within: delta)) +``` + +```objc +// Objective-C + +expect(actual).to(beCloseTo(expected).within(delta)); +``` + +For example, to assert that `10.01` is close to `10`, you can write: + +```swift +// Swift + +expect(10.01).to(beCloseTo(10, within: 0.1)) +``` + +```objc +// Objective-C + +expect(@(10.01)).to(beCloseTo(@10).within(0.1)); +``` + +There is also an operator shortcut available in Swift: + +```swift +// Swift + +expect(actual) ≈ expected +expect(actual) ≈ (expected, delta) + +``` +(Type option+x to get `≈` on a U.S. keyboard) + +The former version uses the default delta of 0.0001. Here is yet another way to do this: + +```swift +// Swift + +expect(actual) ≈ expected ± delta +expect(actual) == expected ± delta + +``` +(Type option+shift+= to get `±` on a U.S. keyboard) + +If you are comparing arrays of floating point numbers, you'll find the following useful: + +```swift +// Swift + +expect([0.0, 2.0]) ≈ [0.0001, 2.0001] +expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1)) + +``` + +> Values given to the `beCloseTo` matcher must be coercable into a + `Double`. + +## Types/Classes + +```swift +// Swift + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)) + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)) +``` + +```objc +// Objective-C + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)); + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)); +``` + +> Instances must be Objective-C objects: subclasses of `NSObject`, + or Swift objects bridged to Objective-C with the `@objc` prefix. + +For example, to assert that `dolphin` is a kind of `Mammal`: + +```swift +// Swift + +expect(dolphin).to(beAKindOf(Mammal)) +``` + +```objc +// Objective-C + +expect(dolphin).to(beAKindOf([Mammal class])); +``` + +> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to + test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`. + +## Truthiness + +```swift +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()) + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()) + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()) + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()) + +// Passes if 'actual' is nil: +expect(actual).to(beNil()) +``` + +```objc +// Objective-C + +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()); + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()); + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()); + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()); + +// Passes if 'actual' is nil: +expect(actual).to(beNil()); +``` + +## Swift Assertions + +If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an assertion, +// such as by calling 'fatalError()' or if a precondition fails: +expect { try somethingThatThrows() }.to(throwAssertion()) +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing an NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the code after the precondition check is not run: +var reachedPoint1 = false +var reachedPoint2 = false +expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true +}.to(throwAssertion()) + +expect(reachedPoint1) == true +expect(reachedPoint2) == false +``` + +Notes: + +* This feature is only available in Swift. +* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_. +* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration. + +## Swift Error Handling + +If you're using Swift 2.0 or newer, you can use the `throwError` matcher to check if an error is thrown. + +Note: +The following code sample references the `Swift.Error` protocol. +This is `Swift.ErrorProtocol` in versions of Swift prior to version 3.0. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an 'Error': +expect { try somethingThatThrows() }.to(throwError()) + +// Passes if 'somethingThatThrows()' throws an error within a particular domain: +expect { try somethingThatThrows() }.to(throwError { (error: Error) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if 'somethingThatThrows()' throws a particular error enum case: +expect { try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if 'somethingThatThrows()' throws an error of a particular type: +expect { try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +When working directly with `Error` values, using the `matchError` matcher +allows you to perform certain checks on the error itself without having to +explicitly cast the error. + +The `matchError` matcher allows you to check whether or not the error: + +- is the same _type_ of error you are expecting. +- represents a particular error value that you are expecting. + +This can be useful when using `Result` or `Promise` types, for example. + +```swift +// Swift + +let actual: Error = ... + +// Passes if 'actual' represents any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.self)) + +// Passes if 'actual' represents the case 'timeout' from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.timeout)) + +// Passes if 'actual' contains an NSError equal to the one provided: +expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil))) +``` + +Note: This feature is only available in Swift. + +## Exceptions + +```swift +// Swift + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name: +expect(actual).to(raiseException(named: name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException(named: name, reason: reason)) + +// Passes if 'actual' raises an exception which passes expectations defined in the given closure: +// (in this case, if the exception's name begins with "a r") +expect { exception.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(beginWith("a r")) +}) +``` + +```objc +// Objective-C + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name +expect(actual).to(raiseException().named(name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException().named(name).reason(reason)) + +// Passes if 'actual' raises an exception and it passes expectations defined in the given block: +// (in this case, if name begins with "a r") +expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(@"a r")); +})); +``` + +Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)). +Only Objective-C code can raise exceptions that Nimble will catch. + +## Collection Membership + +```swift +// Swift + +// Passes if all of the expected values are members of 'actual': +expect(actual).to(contain(expected...)) + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()) +``` + +```objc +// Objective-C + +// Passes if expected is a member of 'actual': +expect(actual).to(contain(expected)); + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()); +``` + +> In Swift `contain` takes any number of arguments. The expectation + passes if all of them are members of the collection. In Objective-C, + `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27). + +For example, to assert that a list of sea creature names contains +"dolphin" and "starfish": + +```swift +// Swift + +expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish")) +``` + +```objc +// Objective-C + +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin")); +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish")); +``` + +> `contain` and `beEmpty` expect collections to be instances of + `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements. + +To test whether a set of elements is present at the beginning or end of +an ordered collection, use `beginWith` and `endWith`: + +```swift +// Swift + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected...)) + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected...)) +``` + +```objc +// Objective-C + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected)); + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected)); +``` + +> `beginWith` and `endWith` expect collections to be instances of + `NSArray`, or ordered Swift collections composed of `Equatable` + elements. + + Like `contain`, in Objective-C `beginWith` and `endWith` only support + a single argument [for now](https://github.com/Quick/Nimble/issues/27). + +For code that returns collections of complex objects without a strict +ordering, there is the `containElementSatisfying` matcher: + +```swift +// Swift + +struct Turtle { + let color: String +} + +let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "green" +})) +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "blue" +}, "that is a turtle with color 'blue'")) + +// The second matcher will incorporate the provided string in the error message +// should it fail +``` + +```objc +// Objective-C + +@interface Turtle : NSObject +@property (nonatomic, readonly, nonnull) NSString *color; +@end + +@implementation Turtle +@end + +NSArray * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(substring)) + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)) + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)) + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()) + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(expected)); + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)); + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)); + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()); + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +## Collection Elements + +Nimble provides a means to check that all elements of a collection pass a given expectation. + +### Swift + +In Swift, the collection must be an instance of a type conforming to +`Sequence`. + +```swift +// Swift + +// Providing a custom function: +expect([1, 2, 3, 4]).to(allPass { $0! < 5 }) + +// Composing the expectation with another matcher: +expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) +``` + +### Objective-C + +In Objective-C, the collection must be an instance of a type which implements +the `NSFastEnumeration` protocol, and whose elements are instances of a type +which subclasses `NSObject`. + +Additionally, unlike in Swift, there is no override to specify a custom +matcher function. + +```objc +// Objective-C + +expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@5))); +``` + +## Collection Count + +```swift +// Swift + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +For Swift, the actual value must be an instance of a type conforming to `Collection`. +For example, instances of `Array`, `Dictionary`, or `Set`. + +For Objective-C, the actual value must be one of the following classes, or their subclasses: + + - `NSArray`, + - `NSDictionary`, + - `NSSet`, or + - `NSHashTable`. + +## Notifications + +```swift +// Swift +let testNotification = Notification(name: "Foo", object: nil) + +// passes if the closure in expect { ... } posts a notification to the default +// notification center. +expect { + NotificationCenter.default.postNotification(testNotification) +}.to(postNotifications(equal([testNotification])) + +// 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)) +``` + +> This matcher is only available in Swift. + +## Matching a value to any of a group of matchers + +```swift +// Swift + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7))) + +// in Swift you also have the option to use the || operator to achieve a similar function +expect(82).to(beLessThan(50) || beGreaterThan(80)) +``` + +```objc +// Objective-C + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7))) +``` + +Note: This matcher allows you to chain any number of matchers together. This provides flexibility, + but if you find yourself chaining many matchers together in one test, consider whether you + could instead refactor that single test into multiple, more precisely focused tests for + better coverage. + +## Custom Validation + +```swift +// Swift + +// passes if .succeeded is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).to(succeed()) + +// passes if .failed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).notTo(succeed()) +``` + +The `String` provided with `.failed()` is shown when the test fails. + +When using `toEventually()` be careful not to make state changes or run process intensive code since this closure will be ran many times. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `Predicate` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> Predicate { + // Can be shortened to: + // Predicate { actual in ... } + // + // But shown with types here for clarity. + return Predicate { (actual: Expression) throws -> PredicateResult in + let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>") + if let actualValue = try actualExpression.evaluate() { + return PredicateResult( + bool: actualValue == expectedValue!, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} +``` + +The return value of a `Predicate` closure is a `PredicateResult` that indicates +whether the actual value matches the expectation and what error message to +display on failure. + +> The actual `equal` matcher function does not match when + `expected` are nil; the example above has been edited for brevity. + +Since matchers are just Swift functions, you can define them anywhere: +at the top of your test file, in a file shared by all of your tests, or +in an Xcode project you distribute to others. + +> If you write a matcher you think everyone can use, consider adding it + to Nimble's built-in set of matchers by sending a pull request! Or + distribute it yourself via GitHub. + +For examples of how to write your own matchers, just check out the +[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers) +to see how Nimble's built-in set of matchers are implemented. You can +also check out the tips below. + +## PredicateResult + +`PredicateResult` is the return struct that `Predicate` return to indicate +success and failure. A `PredicateResult` is made up of two values: +`PredicateStatus` and `ExpectationMessage`. + +Instead of a boolean, `PredicateStatus` captures a trinary set of values: + +```swift +// Swift + +public enum PredicateStatus { +// The predicate "passes" with the given expression +// eg - expect(1).to(equal(1)) +case matches + +// The predicate "fails" with the given expression +// eg - expect(1).toNot(equal(1)) +case doesNotMatch + +// The predicate never "passes" with the given expression, even if negated +// eg - expect(nil as Int?).toNot(equal(1)) +case fail + +// ... +} +``` + +Meanwhile, `ExpectationMessage` provides messaging semantics for error reporting. + +```swift +// Swift + +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// ... +} +``` + +Predicates should usually depend on either `.expectedActualValueTo(..)` or +`.fail(..)` when reporting errors. Special cases can be used for the other enum +cases. + +Finally, if your Predicate utilizes other Predicates, you can utilize +`.appended(details:)` and `.appended(message:)` methods to annotate an existing +error with more details. + +A common message to append is failing on nils. For that, `.appendedBeNilHint()` +can be used. + +## Lazy Evaluation + +`actualExpression` is a lazy, memoized closure around the value provided to the +`expect` function. The expression can either be a closure or a value directly +passed to `expect(...)`. In order to determine whether that value matches, +custom matchers should call `actualExpression.evaluate()`: + +```swift +// Swift + +public func beNil() -> Predicate { + // Predicate.simpleNilable(..) automatically generates ExpectationMessage for + // us based on the string we provide to it. Also, the 'Nilable' postfix indicates + // that this Predicate supports matching against nil actualExpressions, instead of + // always resulting in a PredicateStatus.fail result -- which is true for + // Predicate.simple(..) + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} +``` + +In the above example, `actualExpression` is not `nil` -- it is a closure +that returns a value. The value it returns, which is accessed via the +`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil` +matcher function returns `true`, indicating that the expectation passed. + +## Type Checking via Swift Generics + +Using Swift's generics, matchers can constrain the type of the actual value +passed to the `expect` function by modifying the return type. + +For example, the following matcher, `haveDescription`, only accepts actual +values that implement the `Printable` protocol. It checks their `description` +against the one provided to the matcher function, and passes if they are the same: + +```swift +// Swift + +public func haveDescription(description: String) -> Predicate { + return Predicate.simple("have description") { actual in + return PredicateStatus(bool: actual.evaluate().description == description) + } +} +``` + +## Customizing Failure Messages + +When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble +outputs the following failure message when an expectation fails: + +```swift +// where `message` is the first string argument and +// `actual` is the actual value received in `expect(..)` +"expected to \(message), got <\(actual)>" +``` + +You can customize this message by modifying the way you create a `Predicate`. + +### Basic Customization + +For slightly more complex error messaging, receive the created failure message +with `Predicate.define(..)`: + +```swift +// Swift + +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(bool: matches, message: msg) + } +} +``` + +In the example above, `msg` is defined based on the string given to +`Predicate.define`. The code looks akin to: + +```swift +// Swift + +let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedValue))>") +``` + +### Full Customization + +To fully customize the behavior of the Predicate, use the overload that expects +a `PredicateResult` to be returned. + +Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use: + +```swift +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// Emits standard error message with a custom actual value instead of the default. +// eg - "expected to , got " +case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + +// Emits standard error message without mentioning the actual value +// eg - "expected to " +case expectedTo(/* message: */ String) + +// ... +} +``` + +For matchers that compose other matchers, there are a handful of helper +functions to annotate messages. + +`appended(message: String)` is used to append to the original failure message: + +```swift +// produces "expected to be true, got (use beFalse() for inverse)" +// appended message do show up inline in Xcode. +.expectedActualValueTo("be true").appended(message: " (use beFalse() for inverse)") +``` + +For a more comprehensive message that spans multiple lines, use +`appended(details: String)` instead: + +```swift +// produces "expected to be true, got \n\nuse beFalse() for inverse\nor use beNil()" +// details do not show inline in Xcode, but do show up in test logs. +.expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()") +``` + +## 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 +custom matcher. The example below defines the class method +`+[NMBObjCMatcher 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) + } + } +} +``` + +The above allows you to use the matcher from Objective-C: + +```objc +// Objective-C + +expect(actual).to([NMBObjCMatcher beNilMatcher]()); +``` + +To make the syntax easier to use, define a C function that calls the +class method: + +```objc +// Objective-C + +FOUNDATION_EXPORT id beNil() { + return [NMBObjCMatcher beNilMatcher]; +} +``` + +### Properly Handling `nil` in Objective-C Matchers + +When supporting Objective-C, make sure you handle `nil` appropriately. +Like [Cedar](https://github.com/pivotal/cedar/issues/100), +**most matchers do not match with nil**. This is to bring prevent test +writers from being surprised by `nil` values where they did not expect +them. + +Nimble provides the `beNil` matcher function for test writer that want +to make expectations on `nil` objects: + +```objc +// Objective-C + +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. + +```swift + +public func beginWith(startingElement: T) -> NonNilMatcherFunc { + 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 + } +} + +extension NMBObjCMatcher { + public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.evaluate() + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } +} +``` + +## Migrating from the Old Matcher API + +Previously (`<7.0.0`), Nimble supported matchers via the following types: + +- `Matcher` +- `NonNilMatcherFunc` +- `MatcherFunc` + +All of those types have been replaced by `Predicate`. While migrating can be a +lot of work, Nimble currently provides several steps to aid migration of your +custom matchers: + +### Minimal Step - Use `.predicate` + +Nimble provides an extension to the old types that automatically naively +converts those types to the newer `Predicate`. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + 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 + }.predicate +} +``` + +This is the simpliest way to externally support `Predicate` which allows easier +composition than the old Nimble matcher interface, with minimal effort to change. + +### Convert to use `Predicate` Type with Old Matcher Constructor + +The second most convenient step is to utilize special constructors that +`Predicate` supports that closely align to the constructors of the old Nimble +matcher types. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} +``` + +This allows you to completely drop the old types from your code, although the +intended behavior may alter slightly to what is desired. + +### Convert to `Predicate` Type with Preferred Constructor + +Finally, you can convert to the native `Predicate` format using one of the +constructors not used to assist in the migration. + +### Deprecation Roadmap + +Nimble 7 introduces `Predicate` but will support the old types with warning +deprecations. A couple major releases of Nimble will remain backwards +compatible with the old matcher api, although new features may not be +backported. + +The deprecating plan is a 3 major versions removal. Which is as follows: + + 1. Introduce new `Predicate` API, deprecation warning for old matcher APIs. + (Nimble `v7.x.x`) + 2. Introduce warnings on migration-path features (`.predicate`, + `Predicate`-constructors with similar arguments to old API). (Nimble + `v8.x.x`) + 3. Remove old API. (Nimble `v9.x.x`) + + +# Installing Nimble + +> Nimble can be used on its own, or in conjunction with its sister + project, [Quick](https://github.com/Quick/Quick). To install both + Quick and Nimble, follow [the installation instructions in the Quick + Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md). + +Nimble can currently be installed in one of two ways: using CocoaPods, or with +git submodules. + +## Installing Nimble as a Submodule + +To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow +these 4 easy steps: + +1. Clone the Nimble repository +2. Add Nimble.xcodeproj to the Xcode workspace for your project +3. Link Nimble.framework to your test target +4. Start writing expectations! + +For more detailed instructions on each of these steps, +read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick). +Ignore the steps involving adding Quick to your project in order to +install just Nimble. + +## Installing Nimble via CocoaPods + +To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add +Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift +support for CocoaPods. + +```ruby +platform :ios, '8.0' + +source 'https://github.com/CocoaPods/Specs.git' + +# Whatever pods you need for your app go here + +target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do + use_frameworks! + pod 'Nimble', '~> 6.0.0' +end +``` + +Finally run `pod install`. + +## Using Nimble without XCTest + +Nimble is integrated with XCTest to allow it work well when used in Xcode test +bundles, however it can also be used in a standalone app. After installing +Nimble using one of the above methods, there are two additional steps required +to make this work. + +1. Create a custom assertion handler and assign an instance of it to the + global `NimbleAssertionHandler` variable. For example: + +```swift +class MyAssertionHandler : AssertionHandler { + func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) { + if (!assertion) { + print("Expectation failed: \(message.stringValue)") + } + } +} +``` +```swift +// Somewhere before you use any assertions +NimbleAssertionHandler = MyAssertionHandler() +``` + +2. Add a post-build action to fix an issue with the Swift XCTest support + library being unnecessarily copied into your app + * Edit your scheme in Xcode, and navigate to Build -> Post-actions + * Click the "+" icon and select "New Run Script Action" + * Open the "Provide build settings from" dropdown and select your target + * Enter the following script contents: +``` +rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib" +``` + +You can now use Nimble assertions in your code and handle failures as you see +fit. diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift @@ -0,0 +1,17 @@ +import Foundation + +/// Protocol for the assertion handler that Nimble uses for all expectations. +public protocol AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) +} + +/// Global backing interface for assertions that Nimble creates. +/// Defaults to a private test handler that passes through to XCTest. +/// +/// If XCTest is not available, you must assign your own assertion handler +/// before using any matchers, otherwise Nimble will abort the program. +/// +/// @see AssertionHandler +public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in + return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() +}() diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift @@ -0,0 +1,19 @@ +/// AssertionDispatcher allows multiple AssertionHandlers to receive +/// assertion messages. +/// +/// @warning Does not fully dispatch if one of the handlers raises an exception. +/// This is possible with XCTest-based assertion handlers. +/// +public class AssertionDispatcher: AssertionHandler { + let handlers: [AssertionHandler] + + public init(handlers: [AssertionHandler]) { + self.handlers = handlers + } + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + for handler in handlers { + handler.assert(assertion, message: message, location: location) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..cc39636 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift @@ -0,0 +1,100 @@ +import Foundation + +/// A data structure that stores information about an assertion when +/// AssertionRecorder is set as the Nimble assertion handler. +/// +/// @see AssertionRecorder +/// @see AssertionHandler +public struct AssertionRecord: CustomStringConvertible { + /// Whether the assertion succeeded or failed + public let success: Bool + /// The failure message the assertion would display on failure. + public let message: FailureMessage + /// The source location the expectation occurred on. + public let location: SourceLocation + + public var description: String { + return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" + } +} + +/// An AssertionHandler that silently records assertions that Nimble makes. +/// This is useful for testing failure messages for matchers. +/// +/// @see AssertionHandler +public class AssertionRecorder: AssertionHandler { + /// All the assertions that were captured by this recorder + public var assertions = [AssertionRecord]() + + public init() {} + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + assertions.append( + AssertionRecord( + success: assertion, + message: message, + location: location)) + } +} + +/// Allows you to temporarily replace the current Nimble assertion handler with +/// the one provided for the scope of the closure. +/// +/// Once the closure finishes, then the original Nimble assertion handler is restored. +/// +/// @see AssertionHandler +public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) { + let environment = NimbleEnvironment.activeInstance + let oldRecorder = environment.assertionHandler + let capturer = NMBExceptionCapture(handler: nil, finally: ({ + environment.assertionHandler = oldRecorder + })) + environment.assertionHandler = tempAssertionHandler + capturer.tryBlock { + try! closure() + } +} + +/// Captures expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about expectations +/// that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherFailingExpectations +public func gatherExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] { + let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler + let recorder = AssertionRecorder() + let handlers: [AssertionHandler] + + if silently { + handlers = [recorder] + } else { + handlers = [recorder, previousRecorder] + } + + let dispatcher = AssertionDispatcher(handlers: handlers) + withAssertionHandler(dispatcher, closure: closure) + return recorder.assertions +} + +/// Captures failed expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about failed +/// expectations that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherExpectations +/// @see raiseException source for an example use case. +public func gatherFailingExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] { + let assertions = gatherExpectations(silently: silently, closure: closure) + return assertions.filter { assertion in + !assertion.success + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..add7d3f --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,187 @@ +import Foundation + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +private func from(objcPredicate: NMBPredicate) -> Predicate { + return Predicate { actualExpression in + let result = objcPredicate.satisfies(({ try actualExpression.evaluate() }), + location: actualExpression.location) + return result.toSwift() + } +} + +internal struct ObjCMatcherWrapper: Matcher { + let matcher: NMBMatcher + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.matches( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.doesNotMatch( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } +} + +// Equivalent to Expectation, but for Nimble's Objective-C interface +public class NMBExpectation: NSObject { + internal let _actualBlock: () -> NSObject? + internal var _negative: Bool + internal let _file: FileString + internal let _line: UInt + internal var _timeout: TimeInterval = 1.0 + + @objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) { + self._actualBlock = actualBlock + self._negative = negative + self._file = file + self._line = line + } + + private var expectValue: Expectation { + return expect(_file, line: _line) { + self._actualBlock() as NSObject? + } + } + + @objc public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + @objc public var to: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.to(from(objcPredicate: pred)) + } else { + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toNot(from(objcPredicate: pred)) + } else { + self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toNotWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var notTo: (NMBMatcher) -> Void { return toNot } + + @objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + @objc public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toNotEventually: (NMBMatcher) -> Void { + return toEventuallyNot + } + + @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { + return toEventuallyNotWithDescription + } + + @objc public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..a114dff --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,93 @@ +import Foundation + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +// swiftlint:disable line_length +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) throws -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool +// swiftlint:enable line_length + +public class NMBObjCMatcher: NSObject, NMBMatcher { + let _match: MatcherBlock + let _doesNotMatch: MatcherBlock + let canMatchNil: Bool + + public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { + self.canMatchNil = canMatchNil + self._match = matcher + self._doesNotMatch = notMatcher + } + + public convenience init(matcher: @escaping MatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in + return try !matcher(actualExpression, failureMessage) + })) + } + + public convenience init(matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in + return try matcher(actualExpression, failureMessage, false) + }), notMatcher: ({ actualExpression, failureMessage in + return try matcher(actualExpression, failureMessage, true) + })) + } + + private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + do { + if !canMatchNil { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return false + } + } + } catch let error { + failureMessage.actualValue = "an unexpected error thrown: \(error)" + return false + } + return true + } + + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result: Bool + do { + result = try _match(expr, failureMessage) + } catch let error { + failureMessage.stringValue = "unexpected error thrown: <\(error)>" + return false + } + + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result: Bool + do { + result = try _doesNotMatch(expr, failureMessage) + } catch let error { + failureMessage.stringValue = "unexpected error thrown: <\(error)>" + return false + } + + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..e1b5432 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift @@ -0,0 +1,45 @@ +import Dispatch +import Foundation + +/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this +/// class' existence +internal class NimbleEnvironment { + static var activeInstance: NimbleEnvironment { + get { + let env = Thread.current.threadDictionary["NimbleEnvironment"] + if let env = env as? NimbleEnvironment { + return env + } else { + let newEnv = NimbleEnvironment() + self.activeInstance = newEnv + return newEnv + } + } + set { + Thread.current.threadDictionary["NimbleEnvironment"] = newValue + } + } + + // TODO: eventually migrate the global to this environment value + var assertionHandler: AssertionHandler { + get { return NimbleAssertionHandler } + set { NimbleAssertionHandler = newValue } + } + + var suppressTVOSAssertionWarning: Bool = false + var awaiter: Awaiter + + init() { + let timeoutQueue: DispatchQueue + if #available(OSX 10.10, *) { + timeoutQueue = DispatchQueue.global(qos: .userInitiated) + } else { + timeoutQueue = DispatchQueue.global(priority: .high) + } + + awaiter = Awaiter( + waitLock: AssertionWaitLock(), + asyncQueue: .main, + timeoutQueue: timeoutQueue) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..14bb045 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,92 @@ +import Foundation +import XCTest + +/// Default handler for Nimble. This assertion handler passes failures along to +/// XCTest. +public class NimbleXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + recordFailure("\(message.stringValue)\n", location: location) + } + } +} + +/// Alternative handler for Nimble. This assertion handler passes failures along +/// to XCTest by attempting to reduce the failure message size. +public class NimbleShortXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + let msg: String + if let actual = message.actualValue { + msg = "got: \(actual) \(message.postfixActual)" + } else { + msg = "expected \(message.to) \(message.postfixMessage)" + } + recordFailure("\(msg)\n", location: location) + } + } +} + +/// Fallback handler in case XCTest is unavailable. This assertion handler will abort +/// the program if it is invoked. +class NimbleXCTestUnavailableHandler: AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") + } +} + +#if !SWIFT_PACKAGE +/// Helper class providing access to the currently executing XCTestCase instance, if any +@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { + @objc static let sharedInstance = CurrentTestCaseTracker() + + private(set) var currentTestCase: XCTestCase? + + private var stashed_swift_reportFatalErrorsToDebugger: Bool = false + + @objc func testCaseWillStart(_ testCase: XCTestCase) { + #if swift(>=3.2) + stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger + _swift_reportFatalErrorsToDebugger = false + #endif + + currentTestCase = testCase + } + + @objc func testCaseDidFinish(_ testCase: XCTestCase) { + currentTestCase = nil + + #if swift(>=3.2) + _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger + #endif + } +} +#endif + +func isXCTestAvailable() -> Bool { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // XCTest is weakly linked and so may not be present + return NSClassFromString("XCTestCase") != nil +#else + return true +#endif +} + +public func recordFailure(_ message: String, location: SourceLocation) { +#if SWIFT_PACKAGE + XCTFail("\(message)", file: location.file, line: location.line) +#else + if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { + #if swift(>=4) + let line = Int(location.line) + #else + let line = location.line + #endif + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..8f8d360 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) +// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy +class NSException {} +#endif + +// NOTE: This file is not intended to be included in the Xcode project. It +// is picked up by the Swift Package Manager during its build process. + +/// A dummy reimplementation of the `NMBExceptionCapture` class to serve +/// as a stand-in for build and runtime environments that don't support +/// Objective C. +internal class ExceptionCapture { + let finally: (() -> Void)? + + init(handler: ((NSException) -> Void)?, finally: (() -> Void)?) { + self.finally = finally + } + + func tryBlock(_ unsafeBlock: (() -> Void)) { + // We have no way of handling Objective C exceptions in Swift, + // so we just go ahead and run the unsafeBlock as-is + unsafeBlock() + + finally?() + } +} + +/// Compatibility with the actual Objective-C implementation +typealias NMBExceptionCapture = ExceptionCapture diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..e874136 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,116 @@ +import Dispatch +import Foundation + +private enum ErrorResult { + case exception(NSException) + case error(Error) + case none +} + +/// Only classes, protocols, methods, properties, and subscript declarations can be +/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style +/// asynchronous waiting logic so that it may be called from Objective-C and Swift. +internal class NMBWait: NSObject { +// About these kind of lines, `@objc` attributes are only required for Objective-C +// support, so that should be conditional on Darwin platforms and normal Xcode builds +// (non-SwiftPM builds). +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#else + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#endif + + // Using a throwable closure makes this method not objc compatible. + internal class func throwableUntil( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) throws -> Void) { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + // swiftlint:disable:next line_length + let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in + DispatchQueue.main.async { + let capture = NMBExceptionCapture( + handler: ({ exception in + done(.exception(exception)) + }), + finally: ({ }) + ) + capture.tryBlock { + do { + try action { + done(.none) + } + } catch let e { + done(.error(e)) + } + } + } + }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line) + + switch result { + case .incomplete: internalError("Reached .incomplete state for waitUntil(...).") + case .blockedRunLoop: + 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) + case let .raisedException(exception): + fail("Unexpected exception raised: \(exception)") + case let .errorThrown(error): + fail("Unexpected error thrown: \(error)") + case .completed(.exception(let exception)): + fail("Unexpected exception raised: \(exception)") + case .completed(.error(let error)): + fail("Unexpected error thrown: \(error)") + case .completed(.none): // success + break + } + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#else + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> 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." +} + +/// Wait asynchronously until the done closure is called or the timeout has been reached. +/// +/// @discussion +/// Call the done() closure to indicate the waiting has completed. +/// +/// 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) { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..e49bb0c --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1,64 @@ +import Foundation + +/// Make an expectation on a given actual value. The value given is lazily evaluated. +public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { + 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: @escaping () throws -> T?) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Always fails the test with a message and a specified location. +public func fail(_ message: String, location: SourceLocation) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(false, message: FailureMessage(stringValue: message), location: location) +} + +/// Always fails the test with a message. +public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { + fail(message, location: SourceLocation(file: file, line: line)) +} + +/// Always fails the test. +public func fail(_ file: FileString = #file, line: UInt = #line) { + fail("fail() always fails", file: file, line: line) +} + +/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts +internal func nimblePrecondition( + _ expr: @autoclosure() -> Bool, + _ name: @autoclosure() -> String, + _ message: @autoclosure() -> String, + file: StaticString = #file, + line: UInt = #line) { + let result = expr() + if !result { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let e = NSException( + name: NSExceptionName(name()), + reason: message(), + userInfo: nil) + e.raise() +#else + preconditionFailure("\(name()) - \(message())", file: file, line: line) +#endif + } +} + +internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { + fatalError( + "Nimble Bug Found: \(msg) at \(file):\(line).\n" + + "Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " + + "code snippet that caused this error." + ) +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..41625a1 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,125 @@ +import Foundation + +// Deprecated +internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = toNot + do { + let pass = try matcher.doesNotMatch(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { + func run() -> (Bool, FailureMessage) { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let result = try predicate.satisfies(expression) + result.message.update(failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (result.toBoolean(expectation: style), msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } + } + + var result: (Bool, FailureMessage) = (false, FailureMessage()) + if captureExceptions { + let capture = NMBExceptionCapture(handler: ({ exception -> Void in + let msg = FailureMessage() + msg.stringValue = "unexpected exception raised: \(exception)" + result = (false, msg) + }), finally: nil) + capture.tryBlock { + result = run() + } + } else { + result = run() + } + + return result +} + +public struct Expectation { + + public let expression: Expression + + public init(expression: Expression) { + self.expression = expression + } + + public func verify(_ pass: Bool, _ message: FailureMessage) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(pass, message: message, location: expression.location) + } + + ////////////////// OLD API ///////////////////// + + /// DEPRECATED: Tests the actual value using a matcher to match. + public func to(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = execute( + expression, + .toMatch, + matcher.predicate, + to: "to", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + 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) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + toNot(matcher, description: description) + } + + ////////////////// NEW API ///////////////////// + + /// Tests the actual value using a matcher to match. + public func to(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ predicate: Predicate, description: String? = nil) { + toNot(predicate, description: description) + } + + // see: + // - `async` for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift new file mode 100644 index 0000000..7aae341 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift @@ -0,0 +1,264 @@ +import Foundation + +public indirect enum ExpectationMessage { + // --- Primary Expectations --- + /// includes actual value in output ("expected to , got ") + case expectedActualValueTo(/* message: */ String) + /// uses a custom actual value string in output ("expected to , got ") + case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + /// excludes actual value in output ("expected to ") + case expectedTo(/* message: */ String) + /// allows any free-form message ("") + case fail(/* message: */ String) + + // --- Composite Expectations --- + // Generally, you'll want the methods, appended(message:) and appended(details:) instead. + + /// Not Fully Implemented Yet. + case prepends(/* Prepended Message */ String, ExpectationMessage) + + /// appends after an existing message (" (use beNil() to match nils)") + case appends(ExpectationMessage, /* Appended Message */ String) + + /// provides long-form multi-line explainations ("\n\n") + case details(ExpectationMessage, String) + + internal var sampleMessage: String { + let asStr = toString(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. + public var expectedMessage: String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return msg + case let .expectedActualValueTo(msg): + return msg + case let .expectedCustomValueTo(msg, _): + return msg + case let .prepends(_, expectation): + return expectation.expectedMessage + case let .appends(expectation, msg): + return "\(expectation.expectedMessage)\(msg)" + case let .details(expectation, _): + return expectation.expectedMessage + } + } + + /// Appends a message after the primary expectation message + public func appended(message: String) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo, .appends, .prepends: + return .appends(self, message) + case let .details(expectation, msg): + return .details(expectation.appended(message: message), msg) + } + } + + /// Appends a message hinting to use beNil() for when the actual value given was nil. + public func appendedBeNilHint() -> ExpectationMessage { + return appended(message: " (use beNil() to match nils)") + } + + /// Appends a detailed (aka - multiline) message after the primary expectation message + /// Detailed messages will be placed after .appended(message:) calls. + public func appended(details: String) -> ExpectationMessage { + return .details(self, details) + } + + internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(self) + case let .prepends(msg, expectation): + return .prepends(msg, expectation.visitLeafs(f)) + case let .appends(expectation, msg): + return .appends(expectation.visitLeafs(f), msg) + case let .details(expectation, msg): + return .details(expectation.visitLeafs(f), msg) + } + } + + /// Replaces a primary expectation with one returned by f. Preserves all composite expectations + /// that were built upon it (aka - all appended(message:) and appended(details:). + public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(msg) + default: + return msg + } + } + return visitLeafs(walk) + } + + /// Wraps a primary expectation with text before and after it. + /// Alias to prepended(message: before).appended(message: after) + public func wrappedExpectation(before: String, after: String) -> ExpectationMessage { + return prepended(expectation: before).appended(message: after) + } + + /// Prepends a message by modifying the primary expectation + public func prepended(expectation message: String) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case let .expectedTo(msg): + return .expectedTo(message + msg) + case let .expectedActualValueTo(msg): + return .expectedActualValueTo(message + msg) + case let .expectedCustomValueTo(msg, actual): + return .expectedCustomValueTo(message + msg, actual) + default: + return msg.visitLeafs(walk) + } + } + return visitLeafs(walk) + } + + // TODO: test & verify correct behavior + internal func prepended(message: String) -> ExpectationMessage { + return .prepends(message, self) + } + + /// Converts the tree of ExpectationMessages into a final built string. + public func toString(actual: String, expected: String = "expected", to: String = "to") -> String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return "\(expected) \(to) \(msg)" + case let .expectedActualValueTo(msg): + return "\(expected) \(to) \(msg), got \(actual)" + case let .expectedCustomValueTo(msg, actual): + return "\(expected) \(to) \(msg), got \(actual)" + case let .prepends(msg, expectation): + return "\(msg)\(expectation.toString(actual: actual, expected: expected, to: to))" + case let .appends(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\(msg)" + case let .details(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\n\n\(msg)" + } + } + + // Backwards compatibility: converts ExpectationMessage tree to FailureMessage + internal func update(failureMessage: FailureMessage) { + switch self { + case let .fail(msg) where !msg.isEmpty: + failureMessage.stringValue = msg + case .fail: + break + case let .expectedTo(msg): + failureMessage.actualValue = nil + failureMessage.postfixMessage = msg + case let .expectedActualValueTo(msg): + failureMessage.postfixMessage = msg + case let .expectedCustomValueTo(msg, actual): + failureMessage.postfixMessage = msg + failureMessage.actualValue = actual + case let .prepends(msg, expectation): + expectation.update(failureMessage: failureMessage) + if let desc = failureMessage.userDescription { + failureMessage.userDescription = "\(msg)\(desc)" + } else { + failureMessage.userDescription = msg + } + case let .appends(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendMessage(msg) + case let .details(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendDetails(msg) + } + } +} + +extension FailureMessage { + internal func toExpectationMessage() -> ExpectationMessage { + let defaultMsg = FailureMessage() + if expected != defaultMsg.expected || _stringValueOverride != nil { + return .fail(stringValue) + } + + var msg: ExpectationMessage = .fail(userDescription ?? "") + if actualValue != "" && actualValue != nil { + msg = .expectedCustomValueTo(postfixMessage, actualValue ?? "") + } else if postfixMessage != defaultMsg.postfixMessage { + if actualValue == nil { + msg = .expectedTo(postfixMessage) + } else { + msg = .expectedActualValueTo(postfixMessage) + } + } + if postfixActual != defaultMsg.postfixActual { + msg = .appends(msg, postfixActual) + } + if let m = extendedMessage { + msg = .details(msg, m) + } + return msg + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +public class NMBExpectationMessage: NSObject { + private let msg: ExpectationMessage + + internal init(swift msg: ExpectationMessage) { + self.msg = msg + } + + public init(expectedTo message: String) { + self.msg = .expectedTo(message) + } + public init(expectedActualValueTo message: String) { + self.msg = .expectedActualValueTo(message) + } + + public init(expectedActualValueTo message: String, customActualValue actual: String) { + self.msg = .expectedCustomValueTo(message, actual) + } + + public init(fail message: String) { + self.msg = .fail(message) + } + + public init(prepend message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(appendedMessage message: String, child: NMBExpectationMessage) { + self.msg = .appends(child.msg, message) + } + + public init(prependedMessage message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(details message: String, child: NMBExpectationMessage) { + self.msg = .details(child.msg, message) + } + + public func appendedBeNilHint() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: msg.appendedBeNilHint()) + } + + public func toSwift() -> ExpectationMessage { return self.msg } +} + +extension ExpectationMessage { + func toObjectiveC() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..5a233fd --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,99 @@ +import Foundation + +// Memoizes the given closure, only calling the passed +// closure once; even if repeat calls to the returned closure +internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { + var cache: T? + return ({ withoutCaching in + if withoutCaching || cache == nil { + cache = try closure() + } + return cache! + }) +} + +/// Expression represents the closure of the value inside expect(...). +/// Expressions are memoized by default. This makes them safe to call +/// evaluate() multiple times without causing a re-evaluation of the underlying +/// closure. +/// +/// @warning Since the closure can be any code, Objective-C code may choose +/// to raise an exception. Currently, Expression does not memoize +/// exception raising. +/// +/// This provides a common consumable API for matchers to utilize to allow +/// Nimble to change internals to how the captured closure is managed. +public struct Expression { + internal let _expression: (Bool) throws -> T? + internal let _withoutCaching: Bool + public let location: SourceLocation + public let isClosure: Bool + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. The expression is memoized. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { + self._expression = memoizedClosure(expression) + self.location = location + self._withoutCaching = false + self.isClosure = isClosure + } + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param withoutCaching Indicates if the struct should memoize the given + /// closure's result. Subsequent evaluate() calls will + /// not call the given closure if this is true. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { + self._expression = memoizedExpression + self.location = location + self._withoutCaching = withoutCaching + self.isClosure = isClosure + } + + /// Returns a new Expression from the given expression. Identical to a map() + /// on this type. This should be used only to typecast the Expression's + /// closure value. + /// + /// The returned expression will preserve location and isClosure. + /// + /// @param block The block that can cast the current Expression value to a + /// new type. + public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { + return Expression( + expression: ({ try block(self.evaluate()) }), + location: self.location, + isClosure: self.isClosure + ) + } + + public func evaluate() throws -> T? { + return try self._expression(_withoutCaching) + } + + public func withoutCaching() -> Expression { + return Expression( + memoizedExpression: self._expression, + location: location, + withoutCaching: true, + isClosure: isClosure + ) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..2bc57eb --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,92 @@ +import Foundation + +/// Encapsulates the failure message that matchers can report to the end user. +/// +/// This is shared state between Nimble and matchers that mutate this value. +public class FailureMessage: NSObject { + public var expected: String = "expected" + public var actualValue: String? = "" // empty string -> use default; nil -> exclude + public var to: String = "to" + public var postfixMessage: String = "match" + public var postfixActual: String = "" + /// An optional message that will be appended as a new line and provides additional details + /// about the failure. This message will only be visible in the issue navigator / in logs but + /// not directly in the source editor since only a single line is presented there. + public var extendedMessage: String? + public var userDescription: String? + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + internal var hasOverriddenStringValue: Bool { + return _stringValueOverride != nil + } + + public override init() { + } + + public init(stringValue: String) { + _stringValueOverride = stringValue + } + + internal func stripNewlines(_ str: String) -> String { + let whitespaces = CharacterSet.whitespacesAndNewlines + return str + .components(separatedBy: "\n") + .map { line in line.trimmingCharacters(in: whitespaces) } + .joined(separator: "") + } + + internal func computeStringValue() -> String { + var value = "\(expected) \(to) \(postfixMessage)" + if let actualValue = actualValue { + value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" + } + value = stripNewlines(value) + + if let extendedMessage = extendedMessage { + value += "\n\(stripNewlines(extendedMessage))" + } + + if let userDescription = userDescription { + return "\(userDescription)\n\(value)" + } + + return value + } + + internal func appendMessage(_ msg: String) { + if hasOverriddenStringValue { + stringValue += "\(msg)" + } else if actualValue != nil { + postfixActual += msg + } else { + postfixMessage += msg + } + } + + internal func appendDetails(_ msg: String) { + if hasOverriddenStringValue { + if let desc = userDescription { + stringValue = "\(desc)\n\(stringValue)" + } + stringValue += "\n\(msg)" + } else { + if let desc = userDescription { + userDescription = desc + } + extendedMessage = msg + } + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 Jeff Hui. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..cc6c24f --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,121 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) throws -> Bool) -> Predicate + where U: Sequence, T == U.Iterator.Element { + let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in + return PredicateStatus(bool: try passFunc(try actualExpression.evaluate())) + } + return createPredicate(matcher) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate + 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(_ elementMatcher: M) -> Predicate + where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType { + return createPredicate(elementMatcher.predicate) +} + +public func allPass(_ elementPredicate: Predicate) -> Predicate + where S: Sequence { + return createPredicate(elementPredicate) +} + +private func createPredicate(_ elementMatcher: Predicate) -> Predicate + 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) + } + } + failure = failure.replacedExpectation({ expectation in + return .expectedTo(expectation.expectedMessage) + }) + return PredicateResult(status: .matches, message: failure) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate { + return NMBPredicate { actualExpression in + let location = actualExpression.location + let actualValue = try actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + var generator = NSFastEnumerationIterator(value) + while let obj = generator.next() { + if let nsObject = obj as? NSObject { + nsObjects.append(nsObject) + } else { + collectionIsUsable = false + break + } + } + } else { + collectionIsUsable = false + } + + if !collectionIsUsable { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + // swiftlint:disable:next line_length + fail: "allPass can only be used with types which implement NSFastEnumeration (NSArray, NSSet, ...), and whose elements subclass NSObject, got <\(actualValue?.description ?? "nil")>" + ) + ) + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in + if let predicate = matcher as? NMBPredicate { + return predicate.satisfies(({ try expr.evaluate() }), location: expr.location).toSwift() + } else { + let failureMessage = FailureMessage() + let result = matcher.matches( + ({ try! expr.evaluate() }), + failureMessage: failureMessage, + location: expr.location + ) + let expectationMsg = failureMessage.toExpectationMessage() + return PredicateResult( + bool: result, + message: expectationMsg + ) + } + }) + return try pred.satisfies(expr).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Async.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Async.swift new file mode 100644 index 0000000..63e863e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Async.swift @@ -0,0 +1,175 @@ +import Foundation + +/// 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: TimeInterval = 1 + public static var PollInterval: TimeInterval = 0.01 +} + +private func async(style: ExpectationStyle, predicate: Predicate, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate { + return Predicate { actualExpression in + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).\(fnName)(...)" + var lastPredicateResult: PredicateResult? + let result = pollBlock( + pollInterval: poll, + timeoutInterval: timeout, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + lastPredicateResult = try predicate.satisfies(uncachedExpression) + return lastPredicateResult!.toBoolean(expectation: style) + } + switch result { + case .completed: return lastPredicateResult! + case .timedOut: return PredicateResult(status: .fail, message: lastPredicateResult!.message) + case let .errorThrown(error): + return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + case let .raisedException(exception): + return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) + case .blockedRunLoop: + // swiftlint:disable:next line_length + return PredicateResult(status: .fail, message: lastPredicateResult!.message.appended(message: " (timed out, but main thread was unresponsive).")) + case .incomplete: + internalError("Reached .incomplete state for \(fnName)(...).") + } + } +} + +private let toEventuallyRequiresClosureError = FailureMessage( + // swiftlint:disable:next line_length + stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function" +) + +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toMatch, + async(style: .toMatch, predicate: predicate, timeout: timeout, poll: pollInterval, fnName: "toEventually"), + to: "to eventually", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toNotMatch, + async( + style: .toNotMatch, + predicate: predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventuallyNot" + ), + to: "to eventually not", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + } +} + +// Deprecated +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = execute( + expression, + .toMatch, + async( + style: .toMatch, + predicate: matcher.predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventually" + ), + to: "to eventually", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionDoesNotMatch( + expression, + matcher: async( + style: .toNotMatch, + predicate: matcher.predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventuallyNot" + ), + toNot: "to eventually not", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..5d0f5a1 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,68 @@ +import Foundation + +private func matcherMessage(forType expectedType: T.Type) -> String { + return "be a kind of \(String(describing: expectedType))" +} +private func matcherMessage(forClass expectedClass: AnyClass) -> String { + return "be a kind of \(String(describing: expectedClass))" +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "") + return PredicateResult(status: .fail, message: message) + } + message = .expectedCustomValueTo( + "be a kind of \(String(describing: expectedType))", + "<\(String(describing: type(of: validInstance))) instance>" + ) + + return PredicateResult( + bool: validInstance is T, + message: message + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// 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 +public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + let status: PredicateStatus + + let instance = try actualExpression.evaluate() + if let validInstance = instance { + status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "<\(String(describing: type(of: validInstance))) instance>" + ) + } else { + status = .fail + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "" + ) + } + + return PredicateResult(status: status, message: message) + } +} + +extension NMBObjCMatcher { + @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC() + } + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..bc1b02c --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,56 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. +public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedType))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + return PredicateResult( + status: .doesNotMatch, + message: .expectedActualValueTo(errorMessage) + ) + } + + let actualString = "<\(String(describing: type(of: validInstance))) instance>" + + return PredicateResult( + status: PredicateStatus(bool: type(of: validInstance) == expectedType), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAKindOf if you want to match against subclasses +public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedClass))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + let actualString: String + if let validInstance = instance { + actualString = "<\(String(describing: type(of: validInstance))) instance>" + } else { + actualString = "" + } + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let matches = instance != nil && instance!.isMember(of: expectedClass) + #else + let matches = instance != nil && type(of: instance!) == expectedClass + #endif + return PredicateResult( + status: PredicateStatus(bool: matches), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..b1e6f4c --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,138 @@ +import Foundation + +public let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, + expectedValue: NMBDoubleConvertible, + delta: Double) + -> PredicateResult { + let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + return PredicateResult( + bool: actualValue != nil && + abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta, + message: .expectedCustomValueTo(errorMessage, "<\(stringify(actualValue))>") + ) +} + +/// 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: Double, within delta: Double = DefaultDelta) -> Predicate { + 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 { + return Predicate.define { actualExpression in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + 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 + } + } + + @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) -> 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) + } +} +#endif + +public func beCloseTo(_ expectedValues: [Double], within delta: Double = DefaultDelta) -> Predicate<[Double]> { + let errorMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + return Predicate.simple(errorMessage) { actualExpression in + if let actual = try actualExpression.evaluate() { + if actual.count != expectedValues.count { + return .doesNotMatch + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return .doesNotMatch + } + } + return .matches + } + } + return .doesNotMatch + } +} + +// MARK: - Operators + +infix operator ≈ : ComparisonPrecedence + +public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +public 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 +// unexpectantly +precedencegroup PlusMinusOperatorPrecedence { + higherThan: BitwiseShiftPrecedence +} + +infix operator ± : PlusMinusOperatorPrecedence +public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) { + return (expected: lhs, delta: rhs) +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..8d73dcc --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,95 @@ +import Foundation + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return .fail + } + var generator = actualSeq!.makeIterator() + return PredicateStatus(bool: generator.next() == nil) + } +} + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0) + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For NSString instances, it is an empty string. +public func beEmpty() -> Predicate { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || actualString!.length == 0) + } +} + +// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, +// etc, since they conform to Sequence as well as NMBCollection. + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualDictionary = try actualExpression.evaluate() + return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.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 { + return Predicate.simple("be empty") { actualExpression in + let actualArray = try actualExpression.evaluate() + return PredicateStatus(bool: actualArray == nil || actualArray!.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 { + return Predicate.simple("be empty") { actualExpression in + let actual = try actualExpression.evaluate() + return PredicateStatus(bool: actual == nil || actual!.count == 0) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @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) + return try beEmpty().satisfies(expr).toObjectiveC() + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try beEmpty().satisfies(expr).toObjectiveC() + } else if let actualValue = actualValue { + // swiftlint:disable:next line_length + let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + expectedActualValueTo: badTypeErrorMsg, + customActualValue: "\(String(describing: type(of: actualValue))) type" + ) + ) + } + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() + ) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..b86f25d --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { + let errorMessage = "be greater than <\(stringify(expectedValue))>" + return Predicate.simple(errorMessage) { actualExpression in + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil + && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending + return PredicateStatus(bool: matches) + } +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try beGreaterThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..2a3ca4a --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -0,0 +1,44 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + let message = "be greater than or equal to <\(stringify(expectedValue))>" + return Predicate.simple(message) { actualExpression in + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending + return PredicateStatus(bool: matches) + } +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..94758c2 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -0,0 +1,53 @@ +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 { + return Predicate.define { actualExpression in + #if os(Linux) + let actual = try actualExpression.evaluate() as? AnyObject + #else + let actual = try actualExpression.evaluate() as AnyObject? + #endif + + let bool: Bool + #if os(Linux) + bool = actual === (expected as? AnyObject) && actual !== nil + #else + bool = actual === (expected as AnyObject?) && actual !== nil + #endif + return PredicateResult( + bool: bool, + message: .expectedCustomValueTo( + "be identical to \(identityAsString(expected))", + "\(identityAsString(actual))" + ) + ) + } +} + +public func === (lhs: Expectation, rhs: Any?) { + lhs.to(beIdenticalTo(rhs)) +} +public func !== (lhs: Expectation, rhs: Any?) { + lhs.toNot(beIdenticalTo(rhs)) +} + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +/// +/// Alias for "beIdenticalTo". +public func be(_ expected: Any?) -> Predicate { + return beIdenticalTo(expected) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let aExpr = actualExpression.cast { $0 as Any? } + return try beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..e1fbf1e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { + let message = "be less than <\(stringify(expectedValue))>" + return Predicate.simple(message) { actualExpression in + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending + return PredicateStatus(bool: matches) + } +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try beLessThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..c37cb16 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in + let actualValue = try actualExpression.evaluate() + let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false + return PredicateStatus(bool: matches) + } +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..035500e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,167 @@ +import Foundation + +extension Int8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int8Value + } +} + +extension UInt8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint8Value + } +} + +extension Int16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int16Value + } +} + +extension UInt16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint16Value + } +} + +extension Int32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int32Value + } +} + +extension UInt32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint32Value + } +} + +extension Int64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int64Value + } +} + +extension UInt64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint64Value + } +} + +extension Float: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).floatValue + } +} + +extension Double: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).doubleValue + } +} + +extension Int: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).intValue + } +} + +extension UInt: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uintValue + } +} + +internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { + return Predicate { actualExpression in + let result = try matcher.satisfies(actualExpression) + return PredicateResult(status: result.status, message: message) + }.requireNonNil +} + +// MARK: beTrue() / beFalse() + +/// A Nimble matcher that succeeds when the actual value is exactly true. +/// This matcher will not match against nils. +public func beTrue() -> Predicate { + return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> Predicate { + return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> Predicate { + return Predicate.simpleNilable("be truthy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == true) + } + + return PredicateStatus(bool: actualValue == (true as T)) + } + return PredicateStatus(bool: actualValue != nil) + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> Predicate { + return Predicate.simpleNilable("be falsy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == false) + } + + return PredicateStatus(bool: actualValue == (false as T)) + } + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beTruthyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try beTruthy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalsyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try beFalsy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beTrueMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try beTrue().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalseMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try beFalse().matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..387420b --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,19 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> Predicate { + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..a9dbc28 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift @@ -0,0 +1,17 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is Void. +public func beVoid() -> Predicate<()> { + return Predicate.simpleNilable("be void") { actualExpression in + let actualValue: ()? = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue != nil) + } +} + +public func == (lhs: Expectation<()>, rhs: ()) { + lhs.to(beVoid()) +} + +public func != (lhs: Expectation<()>, rhs: ()) { + lhs.toNot(beVoid()) +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..a013f9f --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,60 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's first element +/// is equal to the expected value. +public func beginWith(_ startingElement: T) -> Predicate + where S.Iterator.Element == T { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> Predicate { + return Predicate.simple("begin with <\(startingElement)>") { actualExpression in + guard let collection = try actualExpression.evaluate() else { return .fail } + guard collection.count > 0 else { return .doesNotMatch } + #if os(Linux) + guard let collectionValue = collection.object(at: 0) as? NSObject else { + return .fail + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return PredicateStatus(bool: collectionValue.isEqual(startingElement)) + } +} + +/// A Nimble matcher that succeeds when the actual string contains expected substring +/// where the expected substring's location is zero. +public func beginWith(_ startingSubstring: String) -> Predicate { + return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return PredicateStatus(bool: range != nil && range!.lowerBound == actual.startIndex) + } + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try beginWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..2c84c5c --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,95 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> Predicate + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> Predicate + where S.Iterator.Element == T { + return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let matches = items.all { + return actual.contains($0) + } + return PredicateStatus(bool: matches) + } + return .fail + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> Predicate { + return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let matches = substrings.all { + let range = actual.range(of: $0) + return range != nil && !range!.isEmpty + } + return PredicateStatus(bool: matches) + } + return .fail + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> Predicate { + return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let matches = substrings.all { actual.range(of: $0.description).length != 0 } + return PredicateStatus(bool: matches) + } + return .fail + } +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> Predicate { + return contain(items) +} + +public func contain(_ items: [Any?]) -> Predicate { + return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in + guard let actual = try actualExpression.evaluate() else { return .fail } + let matches = items.all { item in + return item.map { actual.contains($0) } ?? false + } + return PredicateStatus(bool: matches) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try actualExpression.evaluate() + if let value = actualValue as? NMBContainer { + let expr = Expression(expression: ({ value as NMBContainer }), location: location) + + // A straightforward cast on the array causes this to crash, so we have to cast the individual items + let expectedOptionals: [Any?] = expected.map({ $0 as Any? }) + return try contain(expectedOptionals).matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try contain(expected as! [String]).matches(expr, failureMessage: failureMessage) + } else if actualValue != nil { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)" + } else { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..8a23a6c --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,58 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T { + + return Predicate.define { actualExpression in + let message: ExpectationMessage + if predicateDescription == "" { + message = .expectedTo("find object in collection that satisfies predicate") + } else { + message = .expectedTo("find object in collection \(predicateDescription)") + } + + if let sequence = try actualExpression.evaluate() { + for object in sequence { + if predicate(object) { + return PredicateResult(bool: true, message: message) + } + } + + return PredicateResult(bool: false, message: message) + } + + return PredicateResult(status: .fail, message: message) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + extension NMBObjCMatcher { + @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let value = try actualExpression.evaluate() + guard let enumeration = value as? NSFastEnumeration else { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + var iterator = NSFastEnumerationIterator(enumeration) + while let item = iterator.next() { + guard let object = item as? NSObject else { + continue + } + + if predicate(object) { + return true + } + } + + failureMessage.actualValue = nil + failureMessage.postfixMessage = "find object in collection that satisfies predicate" + return false + } + } + } +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..80a06ca --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift @@ -0,0 +1,68 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's last element +/// is equal to the expected value. +public func endWith(_ endingElement: T) -> Predicate + where S.Iterator.Element == T { + 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) + + return PredicateStatus(bool: lastItem == endingElement) + } + return .fail + } +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> Predicate { + 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 { + return .fail + } + #else + let collectionValue = collection.object(at: collection.count - 1) as AnyObject + #endif + + return PredicateStatus(bool: collectionValue.isEqual(endingElement)) + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring +/// where the expected substring's location is the actual string's length minus the +/// expected substring's length. +public func endWith(_ endingSubstring: String) -> Predicate { + return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in + if let collection = try actualExpression.evaluate() { + return PredicateStatus(bool: collection.hasSuffix(endingSubstring)) + } + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try endWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try endWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..5f26f49 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,220 @@ +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. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(status: PredicateStatus(bool: matches), message: msg) + } +} + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: [T: C]?) -> Predicate<[T: C]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult( + status: PredicateStatus(bool: expectedValue! == actualValue!), + message: msg + ) + } +} + +/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection. +/// Items must implement the Equatable protocol. +public func equal(_ expectedValue: [T]?) -> Predicate<[T]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult( + status: .fail, + message: msg + ) + } + return PredicateResult( + bool: expectedValue! == actualValue!, + message: msg + ) + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + if let actualValue = try actualExpression.evaluate() { + let doesNotMatch = PredicateResult( + status: .doesNotMatch, + message: msg + ) + + if expectedValue.count != actualValue.count { + return doesNotMatch + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return doesNotMatch + } else if item != nil && otherItem == nil { + return doesNotMatch + } else if item! != otherItem! { + return doesNotMatch + } + } + + return PredicateResult( + status: .matches, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { stringify($0) }) +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { + if let set = $0 { + return stringify(Array(set).sorted { $0 < $1 }) + } else { + return "nil" + } + }) +} + +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { + return Predicate { actualExpression in + var errorMessage: ExpectationMessage = + .expectedActualValueTo("equal <\(stringify(expectedValue))>") + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + errorMessage = .expectedCustomValueTo( + "equal <\(stringify(expectedValue))>", + "<\(stringify(actualValue))>" + ) + + if expectedValue == actualValue { + return PredicateResult( + status: .matches, + message: errorMessage + ) + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>") + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") + } + return PredicateResult( + status: .doesNotMatch, + message: errorMessage + ) + } + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } else { + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } + } +} + +public func ==(lhs: Expectation, rhs: T?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation, rhs: T?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.toNot(equal(rhs)) +} + +public func == (lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func != (lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.toNot(equal(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try equal(expected).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..3529da8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,65 @@ +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. +// The representation of the collection content is provided in a new line as an `extendedMessage`. + +/// A Nimble matcher that succeeds when the actual Collection's count equals +/// the expected value +public func haveCount(_ expectedValue: T.IndexDistance) -> Predicate { + return Predicate.define { actualExpression in + if let actualValue = try actualExpression.evaluate() { + let message = ExpectationMessage + .expectedCustomValueTo( + "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))", + "\(actualValue.count)" + ) + .appended(details: "Actual Value: \(stringify(actualValue))") + + let result = expectedValue == actualValue.count + return PredicateResult(bool: result, message: message) + } else { + return PredicateResult(status: .fail, message: .fail("")) + } + } +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> Predicate { + return Predicate { actualExpression in + if let actualValue = try actualExpression.evaluate() { + let message = ExpectationMessage + .expectedCustomValueTo( + "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))", + "\(actualValue.count)" + ) + .appended(details: "Actual Value: \(stringify(actualValue))") + + let result = expectedValue == actualValue.count + return PredicateResult(bool: result, message: message) + } else { + return PredicateResult(status: .fail, message: .fail("")) + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage 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) + return try haveCount(expected.intValue).matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable" + failureMessage.actualValue = "\(String(describing: type(of: actualValue)))" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..f738daf --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift @@ -0,0 +1,29 @@ +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 { + 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) + } + } + + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +extension NMBObjCMatcher { + @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBPredicate { actualExpression in + let actual = actualExpression.cast { $0 as? String } + return try match(expected.description).satisfies(actual).toObjectiveC() + } + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..4ad71d4 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,76 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.define { actualExpression in + let actualError = try actualExpression.evaluate() + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + error: error + ) + + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.define { actualExpression in + let actualError = try actualExpression.evaluate() + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + error: error + ) + + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> Predicate { + return Predicate.define { actualExpression in + let actualError = try actualExpression.evaluate() + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + errorType: errorType + ) + + var matches = false + if actualError as? T != nil { + matches = true + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..abcafa9 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,85 @@ +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil +/// values are received in an expectation. +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct MatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try matcher(actualExpression, failureMessage) + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try !matcher(actualExpression, failureMessage) + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} + +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// Unlike MatcherFunc, this will always fail if an expectation contains nil. +/// This applies regardless of using to() or toNot(). +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct NonNilMatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try !matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return true + } + return false + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..6f8f103 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,154 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +@available(*, deprecated, message: "Use Predicate instead") +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +extension Matcher { + var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } + + var toClosure: (Expression, FailureMessage, Bool) throws -> Bool { + return ({ expr, msg, expectedResult in + if expectedResult { + return try self.matches(expr, failureMessage: msg) + } else { + return try self.doesNotMatch(expr, failureMessage: msg) + } + }) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +/// Objective-C interface to the Swift variant of Matcher. +@objc public protocol NMBMatcher { + func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool + func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool +} +#endif + +/// Protocol for types that support contain() matcher. +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a +//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet +#endif + +extension NSArray: NMBContainer {} +extension NSSet: NMBContainer {} + +/// Protocol for types that support only beEmpty(), haveCount() matchers +public protocol NMBCollection { + var count: Int { get } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable: NMBCollection {} +#endif + +extension NSSet: NMBCollection {} +extension NSIndexSet: NMBCollection {} +extension NSDictionary: NMBCollection {} + +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} + +extension NSArray: NMBOrderedCollection {} + +public protocol NMBDoubleConvertible { + var doubleValue: CDouble { get } +} + +extension Double: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self + } +} + +extension Float: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension CGFloat: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension NSNumber: NMBDoubleConvertible { +} + +private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.locale = Locale(identifier: "en_US_POSIX") + + return formatter +}() + +extension Date: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension NSDate: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension Date: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: self) + } +} + +extension NSDate: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) + } +} + +/// 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 os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@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 { + return compare(otherObject as! NSNumber) + } +} +extension NSString: NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! String) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..16af011 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,98 @@ +import Foundation + +// A workaround to SR-6419. +extension NotificationCenter { +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + #if swift(>=4.0) + #if swift(>=4.0.2) + #else + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #elseif swift(>=3.2) + #if swift(>=3.2.2) + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif +#endif +} + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + // swiftlint:disable:next line_length + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil, using: { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + }) + } + + deinit { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + if let token = self.token { + self.notificationCenter.removeObserver(token) + } + #else + if let token = self.token as? AnyObject { + self.notificationCenter.removeObserver(token) + } + #endif + } +} + +private let mainThread = pthread_self() + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = .default) + -> Predicate + where T: Matcher, T.ValueType == [Notification] +{ + _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + 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 failureMessage = FailureMessage() + let match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) + if collector.observedNotifications.isEmpty { + failureMessage.actualValue = "no notifications" + } else { + failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" + } + return PredicateResult(bool: match, message: failureMessage.toExpectationMessage()) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift new file mode 100644 index 0000000..19fd322 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift @@ -0,0 +1,352 @@ +// New Matcher API +// +import Foundation + +/// A Predicate is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate +/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble +/// matcher API. +/// +/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, +/// predicates are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +public struct Predicate { + fileprivate var matcher: (Expression) throws -> PredicateResult + + /// Constructs a predicate that knows how take a given value + public init(_ matcher: @escaping (Expression) throws -> PredicateResult) { + self.matcher = matcher + } + + /// Uses a predicate on a given value to see if it passes the predicate. + /// + /// @param expression The value to run the predicate's logic against + /// @returns A predicate result indicate passing or failing and an associated error message. + public func satisfies(_ expression: Expression) throws -> PredicateResult { + return try matcher(expression) + } +} + +/// Provides convenience helpers to defining predicates +extension Predicate { + /// Like Predicate() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (Expression) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual) + }.requireNonNil + } + + /// 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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + }.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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + } + } +} + +extension Predicate { + /// Provides a simple predicate definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the predicate's actual value cannot pass with `nil` given. + public static func simple(_ msg: String, matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + }.requireNonNil + } + + /// Provides a simple predicate definition that provides no control over the predefined + /// 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) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + } + } +} + +// The Expectation style intended for comparison to a PredicateStatus. +public enum ExpectationStyle { + case toMatch, toNotMatch +} + +/// The value that a Predicates return to describe if the given (actual) value matches the +/// predicate. +public struct PredicateResult { + /// Status indicates if the predicate matches, does not match, or fails. + public var status: PredicateStatus + /// The error message that can be displayed if it does not match + public var message: ExpectationMessage + + /// Constructs a new PredicateResult with a given status and error message + public init(status: PredicateStatus, message: ExpectationMessage) { + self.status = status + self.message = message + } + + /// Shorthand to PredicateResult(status: PredicateStatus(bool: bool), message: message) + public init(bool: Bool, message: ExpectationMessage) { + self.status = PredicateStatus(bool: bool) + self.message = message + } + + /// Converts the result to a boolean based on what the expectation intended + public func toBoolean(expectation style: ExpectationStyle) -> Bool { + return status.toBoolean(expectation: style) + } +} + +/// PredicateStatus is a trinary that indicates if a Predicate matches a given value or not +public enum PredicateStatus { + /// Matches indicates if the predicate / matcher passes with the given value + /// + /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. + case matches + /// DoesNotMatch indicates if the predicate / matcher fails with the given value, but *would* + /// succeed if the expectation was inverted. + /// + /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. + case doesNotMatch + /// Fail indicates the predicate will never satisfy with the given value in any case. + /// A perfect example is that most matchers fail whenever given `nil`. + /// + /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. + /// Note: Predicate's `requireNonNil` property will also provide this feature mostly for free. + /// Your predicate will still need to guard against nils, but error messaging will be + /// handled for you. + case fail + + /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). + public init(bool matches: Bool) { + if matches { + self = .matches + } else { + self = .doesNotMatch + } + } + + private func shouldMatch() -> Bool { + switch self { + case .matches: return true + case .doesNotMatch, .fail: return false + } + } + + private func shouldNotMatch() -> Bool { + switch self { + case .doesNotMatch: return true + case .matches, .fail: return false + } + } + + /// Converts the PredicateStatus result to a boolean based on what the expectation intended + internal func toBoolean(expectation style: ExpectationStyle) -> Bool { + if style == .toMatch { + return shouldMatch() + } else { + return shouldNotMatch() + } + } +} + +// Backwards compatibility until Old Matcher API removal +extension Predicate: Matcher { + /// Compatibility layer for old Matcher API, deprecated + public static func fromDeprecatedFullClosure(_ matcher: @escaping (Expression, FailureMessage, Bool) throws -> Bool) -> Predicate { + return Predicate { actual in + let failureMessage = FailureMessage() + let result = try matcher(actual, failureMessage, true) + return PredicateResult( + status: PredicateStatus(bool: result), + message: failureMessage.toExpectationMessage() + ) + } + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Emulates the MatcherFunc API + public static func fromDeprecatedClosure(_ matcher: @escaping (Expression, 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() + ) + } + + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Same as calling .predicate on a MatcherFunc or NonNilMatcherFunc type. + public static func fromDeprecatedMatcher(_ matcher: M) -> Predicate where M: Matcher, M.ValueType == T { + return self.fromDeprecatedFullClosure(matcher.toClosure) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toMatch) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toNotMatch) + } +} + +extension Predicate { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (Expression, PredicateResult) throws -> PredicateResult) -> Predicate { + return Predicate { actual -> PredicateResult in + let result = try self.satisfies(actual) + return try f(actual, result) + } + } + + /// Returns a new Predicate based on the current one that always fails if nil is given as + /// the actual value. + /// + /// This replaces `NonNilMatcherFunc`. + public var requireNonNil: Predicate { + return after { actual, result in + if try actual.evaluate() == nil { + return PredicateResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public typealias PredicateBlock = (_ actualExpression: Expression) throws -> NMBPredicateResult + +public class NMBPredicate: NSObject { + private let predicate: PredicateBlock + + public init(predicate: @escaping PredicateBlock) { + self.predicate = predicate + } + + func satisfies(_ expression: @escaping () throws -> NSObject?, location: SourceLocation) -> NMBPredicateResult { + let expr = Expression(expression: expression, location: location) + do { + return try self.predicate(expr) + } catch let error { + return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")).toObjectiveC() + } + } +} + +extension NMBPredicate: NMBMatcher { + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toMatch) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toNotMatch) + } +} + +final public class NMBPredicateResult: NSObject { + public var status: NMBPredicateStatus + public var message: NMBExpectationMessage + + public init(status: NMBPredicateStatus, message: NMBExpectationMessage) { + self.status = status + self.message = message + } + + public init(bool success: Bool, message: NMBExpectationMessage) { + self.status = NMBPredicateStatus.from(bool: success) + self.message = message + } + + public func toSwift() -> PredicateResult { + return PredicateResult(status: status.toSwift(), + message: message.toSwift()) + } +} + +extension PredicateResult { + public func toObjectiveC() -> NMBPredicateResult { + return NMBPredicateResult(status: status.toObjectiveC(), message: message.toObjectiveC()) + } +} + +final public class NMBPredicateStatus: NSObject { + private let status: Int + private init(status: Int) { + self.status = status + } + + public static let matches: NMBPredicateStatus = NMBPredicateStatus(status: 0) + public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1) + public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2) + + public override var hashValue: Int { return self.status.hashValue } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherPredicate = object as? NMBPredicateStatus else { + return false + } + return self.status == otherPredicate.status + } + + public static func from(status: PredicateStatus) -> NMBPredicateStatus { + switch status { + case .matches: return self.matches + case .doesNotMatch: return self.doesNotMatch + case .fail: return self.fail + } + } + + public static func from(bool success: Bool) -> NMBPredicateStatus { + return self.from(status: PredicateStatus(bool: success)) + } + + public func toSwift() -> PredicateStatus { + switch status { + case NMBPredicateStatus.matches.status: return .matches + case NMBPredicateStatus.doesNotMatch.status: return .doesNotMatch + case NMBPredicateStatus.fail.status: return .fail + default: + internalError("Unhandle status for NMBPredicateStatus") + } + } +} + +extension PredicateStatus { + public func toObjectiveC() -> NMBPredicateStatus { + return NMBPredicateStatus.from(status: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..459d2cd --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,204 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +/// 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( + named: String? = nil, + reason: String? = nil, + userInfo: NSDictionary? = nil, + closure: ((NSException) -> Void)? = nil) -> Predicate { + return Predicate { actualExpression in + var exception: NSException? + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + _ = try! actualExpression.evaluate() + } + + 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()) + } +} + +// swiftlint:disable:next function_parameter_count +internal func setFailureMessageForException( + _ failureMessage: FailureMessage, + exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) { + failureMessage.postfixMessage = "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 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" + } +} + +internal func exceptionMatchesNonNilFieldsOrClosure( + _ exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) -> Bool { + var matches = false + + if let exception = exception { + matches = true + + if let named = named, exception.name.rawValue != named { + matches = false + } + if reason != nil && exception.reason != reason { + matches = false + } + if let userInfo = userInfo, let exceptionUserInfo = exception.userInfo, + (exceptionUserInfo as NSDictionary) != userInfo { + matches = false + } + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(exception) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} + +public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher { + internal var _name: String? + internal var _reason: String? + internal var _userInfo: NSDictionary? + internal var _block: ((NSException) -> Void)? + + internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) { + _name = name + _reason = reason + _userInfo = userInfo + _block = block + } + + @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 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( + 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 + ) + }) + } +} + +extension NMBObjCMatcher { + @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift new file mode 100644 index 0000000..2b9eb21 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift @@ -0,0 +1,76 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAllOf(matchers.map { $0.predicate }) +} + +internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { + return Predicate.define { actualExpression in + var postfixMessages = [String]() + var matches = true + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toNotMatch) { + matches = false + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match all of: " + postfixMessages.joined(separator: ", and "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match all of: " + postfixMessages.joined(separator: ", and ") + ) + } + + return PredicateResult(bool: matches, message: msg) + } +} + +public func && (left: Predicate, right: Predicate) -> Predicate { + return satisfyAllOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAllOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..57b15fd --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,84 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers.map { $0.predicate }) +} + +internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { + return Predicate.define { actualExpression in + var postfixMessages = [String]() + var matches = false + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toMatch) { + matches = true + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match one of: " + postfixMessages.joined(separator: ", or "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match one of: " + postfixMessages.joined(separator: ", or ") + ) + } + + return PredicateResult(bool: matches, message: msg) + } +} + +public func || (left: Predicate, right: Predicate) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAnyOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..035c744 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,52 @@ +import Foundation + +public func throwAssertion() -> Predicate { + return Predicate { actualExpression in + #if arch(x86_64) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + let message = ExpectationMessage.expectedTo("throw an assertion") + + var actualError: Error? + let caughtException: BadInstructionException? = catchBadInstruction { + #if os(tvOS) + if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { + print() + print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + + "fatal error while using throwAssertion(), please disable 'Debug Executable' " + + "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + + "'Debug Executable'. If you've already done that, suppress this warning " + + "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + + "This is required because the standard methods of catching assertions " + + "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + + "debugger uses is the fallback method for tvOS." + ) + print() + NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true + } + #endif + do { + try actualExpression.evaluate() + } catch { + actualError = error + } + } + + if let actualError = actualError { + return PredicateResult( + bool: false, + message: message.appended(message: "; threw error instead <\(actualError)>") + ) + } 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. Mac, iPhone 5s or later simulators). You can silence this error " + + "by placing the test case inside an #if arch(x86_64) or (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) conditional statement") + // swiftlint:disable:previous line_length + #endif + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..d294ba3 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,264 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError() -> Predicate { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + if let actualError = actualError { + return PredicateResult(bool: true, message: .expectedCustomValueTo("throw any error", "<\(actualError)>")) + } else { + return PredicateResult(bool: false, message: .expectedCustomValueTo("throw any error", "no error")) + } + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError( + errorType: T.Type, + closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + let failureMessage = FailureMessage() + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: nil, + errorType: errorType, + closure: closure + ) + + var matches = false + if let actualError = actualError { + matches = true + + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + } else { + matches = (actualError is T) + // The closure expects another ErrorProtocol as argument, so this + // is _supposed_ to fail, so that it becomes more obvious. + if let closure = closure { + let assertions = gatherExpectations { + if let actual = actualError as? T { + closure(actual) + } + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + } + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// 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 { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + let failureMessage = FailureMessage() + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// values of the existential type `Error` in the closure. +/// +/// The closure only gets called when an error was thrown. +public func throwError(closure: @escaping ((T) -> Void)) -> Predicate { + return Predicate { actualExpression in + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch { + actualError = error + } + + let failureMessage = FailureMessage() + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError as? T { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if !messages.isEmpty { + matches = false + } + } + + return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift new file mode 100644 index 0000000..01369bb --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift @@ -0,0 +1,37 @@ +/** + Used by the `toSucceed` matcher. + + This is the return type for the closure. + */ +public enum ToSucceedResult { + case succeeded + case failed(reason: String) +} + +/** + A Nimble matcher that takes in a closure for validation. + + Return `.succeeded` when the validation succeeds. + Return `.failed` with a failure reason when the validation fails. + */ +public func succeed() -> Predicate<() -> ToSucceedResult> { + return Predicate.define { actualExpression in + let optActual = try actualExpression.evaluate() + guard let actual = optActual else { + return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) + } + + switch actual() { + case .succeeded: + return PredicateResult( + bool: true, + message: .expectedCustomValueTo("succeed", "") + ) + case .failed(let reason): + return PredicateResult( + bool: false, + message: .expectedCustomValueTo("succeed", " because <\(reason)>") + ) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..2bbc693 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,13 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#if TARGET_OS_TV + #import "CwlPreconditionTesting_POSIX.h" +#else + #import "CwlPreconditionTesting.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Await.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Await.swift new file mode 100644 index 0000000..cb672ad --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Await.swift @@ -0,0 +1,381 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + import CDispatch +#endif + +private let timeoutLeeway = DispatchTimeInterval.milliseconds(1) +private let pollLeeway = DispatchTimeInterval.milliseconds(1) + +/// Stores debugging information about callers +internal struct WaitingInfo: CustomStringConvertible { + let name: String + let file: FileString + let lineNumber: UInt + + var description: String { + return "\(name) at \(file):\(lineNumber)" + } +} + +internal protocol WaitLock { + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) + func releaseWaitingLock() + func isWaitingLocked() -> Bool +} + +internal class AssertionWaitLock: WaitLock { + private var currentWaiter: WaitingInfo? + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let isMainThread = Thread.isMainThread + #else + let isMainThread = _CFIsMainThread() + #endif + nimblePrecondition( + isMainThread, + "InvalidNimbleAPIUsage", + "\(fnName) can only run on the main thread." + ) + nimblePrecondition( + currentWaiter == nil, + "InvalidNimbleAPIUsage", + "Nested async expectations are not allowed to avoid creating flaky tests.\n\n" + + "The call to\n\t\(info)\n" + + "triggered this exception because\n\t\(currentWaiter!)\n" + + "is currently managing the main run loop." + ) + currentWaiter = info + } + + func isWaitingLocked() -> Bool { + return currentWaiter != nil + } + + func releaseWaitingLock() { + currentWaiter = nil + } +} + +internal enum AwaitResult { + /// Incomplete indicates None (aka - this value hasn't been fulfilled yet) + case incomplete + /// TimedOut indicates the result reached its defined timeout limit before returning + case timedOut + /// BlockedRunLoop indicates the main runloop is too busy processing other blocks to trigger + /// the timeout code. + /// + /// This may also mean the async code waiting upon may have never actually ran within the + /// required time because other timers & sources are running on the main run loop. + case blockedRunLoop + /// The async block successfully executed and returned a given result + case completed(T) + /// When a Swift Error is thrown + case errorThrown(Error) + /// When an Objective-C Exception is raised + case raisedException(NSException) + + func isIncomplete() -> Bool { + switch self { + case .incomplete: return true + default: return false + } + } + + func isCompleted() -> Bool { + switch self { + case .completed: return true + default: return false + } + } +} + +/// Holds the resulting value from an asynchronous expectation. +/// This class is thread-safe at receiving an "response" to this promise. +internal class AwaitPromise { + private(set) internal var asyncResult: AwaitResult = .incomplete + private var signal: DispatchSemaphore + + init() { + signal = DispatchSemaphore(value: 1) + } + + deinit { + signal.signal() + } + + /// Resolves the promise with the given result if it has not been resolved. Repeated calls to + /// this method will resolve in a no-op. + /// + /// @returns a Bool that indicates if the async result was accepted or rejected because another + /// value was received first. + func resolveResult(_ result: AwaitResult) -> Bool { + if signal.wait(timeout: .now()) == .success { + self.asyncResult = result + return true + } else { + return false + } + } +} + +internal struct AwaitTrigger { + let timeoutSource: DispatchSourceTimer + let actionSource: DispatchSourceTimer? + let start: () throws -> Void +} + +/// Factory for building fully configured AwaitPromises and waiting for their results. +/// +/// This factory stores all the state for an async expectation so that Await doesn't +/// doesn't have to manage it. +internal class AwaitPromiseBuilder { + let awaiter: Awaiter + let waitLock: WaitLock + let trigger: AwaitTrigger + let promise: AwaitPromise + + internal init( + awaiter: Awaiter, + waitLock: WaitLock, + promise: AwaitPromise, + trigger: AwaitTrigger) { + self.awaiter = awaiter + self.waitLock = waitLock + self.promise = promise + self.trigger = trigger + } + + func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + // = Discussion = + // + // There's a lot of technical decisions here that is useful to elaborate on. This is + // definitely more lower-level than the previous NSRunLoop based implementation. + // + // + // Why Dispatch Source? + // + // + // We're using a dispatch source to have better control of the run loop behavior. + // A timer source gives us deferred-timing control without having to rely as much on + // a run loop's traditional dispatching machinery (eg - NSTimers, DefaultRunLoopMode, etc.) + // which is ripe for getting corrupted by application code. + // + // And unlike dispatch_async(), we can control how likely our code gets prioritized to + // executed (see leeway parameter) + DISPATCH_TIMER_STRICT. + // + // This timer is assumed to run on the HIGH priority queue to ensure it maintains the + // highest priority over normal application / test code when possible. + // + // + // Run Loop Management + // + // In order to properly interrupt the waiting behavior performed by this factory class, + // this timer stops the main run loop to tell the waiter code that the result should be + // checked. + // + // In addition, stopping the run loop is used to halt code executed on the main run loop. + #if swift(>=4.0) + trigger.timeoutSource.schedule( + deadline: DispatchTime.now() + timeoutInterval, + repeating: .never, + leeway: timeoutLeeway + ) + #else + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway + ) + #endif + trigger.timeoutSource.setEventHandler { + guard self.promise.asyncResult.isIncomplete() else { return } + let timedOutSem = DispatchSemaphore(value: 0) + let semTimedOutOrBlocked = DispatchSemaphore(value: 0) + semTimedOutOrBlocked.signal() + let runLoop = CFRunLoopGetMain() + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + let now = DispatchTime.now() + forcefullyAbortTimeout + let didNotTimeOut = timedOutSem.wait(timeout: now) != .success + let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success + if didNotTimeOut && timeoutWasNotTriggered { + if self.promise.resolveResult(.blockedRunLoop) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + return self + } + + /// Blocks for an asynchronous result. + /// + /// @discussion + /// This function must be executed on the main thread and cannot be nested. This is because + /// this function (and it's related methods) coordinate through the main run loop. Tampering + /// with the run loop can cause undesirable behavior. + /// + /// This method will return an AwaitResult in the following cases: + /// + /// - The main run loop is blocked by other operations and the async expectation cannot be + /// be stopped. + /// - The async expectation timed out + /// - The async expectation succeeded + /// - The async expectation raised an unexpected exception (objc) + /// - The async expectation raised an unexpected error (swift) + /// + /// The returned AwaitResult will NEVER be .incomplete. + func wait(_ fnName: String = #function, file: FileString = #file, line: UInt = #line) -> AwaitResult { + waitLock.acquireWaitingLock( + fnName, + file: file, + line: line) + + let capture = NMBExceptionCapture(handler: ({ exception in + _ = self.promise.resolveResult(.raisedException(exception)) + }), finally: ({ + self.waitLock.releaseWaitingLock() + })) + capture.tryBlock { + do { + try self.trigger.start() + } catch let error { + _ = self.promise.resolveResult(.errorThrown(error)) + } + 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) + _ = RunLoop.current.run(mode: .default, before: .distantFuture) + #else + _ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture) + #endif + } + + self.trigger.timeoutSource.cancel() + if let asyncSource = self.trigger.actionSource { + asyncSource.cancel() + } + } + + return promise.asyncResult + } +} + +internal class Awaiter { + let waitLock: WaitLock + let timeoutQueue: DispatchQueue + let asyncQueue: DispatchQueue + + internal init( + waitLock: WaitLock, + asyncQueue: DispatchQueue, + timeoutQueue: DispatchQueue) { + self.waitLock = waitLock + self.asyncQueue = asyncQueue + self.timeoutQueue = timeoutQueue + } + + private func createTimerSource(_ queue: DispatchQueue) -> DispatchSourceTimer { + return DispatchSource.makeTimerSource(flags: .strict, queue: queue) + } + + func performBlock( + file: FileString, + line: UInt, + _ closure: @escaping (@escaping (T) -> Void) throws -> Void + ) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + var completionCount = 0 + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) { + try closure { + completionCount += 1 + if completionCount < 2 { + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } else { + fail("waitUntil(..) expects its completion closure to be only called once", + file: file, line: line) + } + } + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } + + func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + 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))) + #if swift(>=4.0) + asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway) + #else + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + #endif + asyncSource.setEventHandler { + do { + if let result = try closure() { + if promise.resolveResult(.completed(result)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } catch let error { + if promise.resolveResult(.errorThrown(error)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } + asyncSource.resume() + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } +} + +internal func pollBlock( + pollInterval: TimeInterval, + timeoutInterval: TimeInterval, + file: FileString, + line: UInt, + fnName: String = #function, + expression: @escaping () throws -> Bool) -> AwaitResult { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let result = awaiter.poll(pollInterval) { () throws -> Bool? in + if try expression() { + return true + } + return nil + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..074cb20 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,59 @@ +import Foundation + +// Generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + postfixMessageVerb: String = "throw", + actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) { + failureMessage.postfixMessage = "\(postfixMessageVerb) error" + + if let error = error { + failureMessage.postfixMessage += " <\(error)>" + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } + if error == nil && errorType == nil && closure == nil { + failureMessage.postfixMessage = "\(postfixMessageVerb) any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool { + return actualError._domain == expectedError._domain + && actualError._code == expectedError._code +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift @@ -0,0 +1,12 @@ +import Foundation + +extension Sequence { + internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool { + for item in self { + if !fn(item) { + return false + } + } + return true + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift @@ -0,0 +1,31 @@ +import Foundation + +// Ideally we would always use `StaticString` as the type for tracking the file name +// that expectations originate from, for consistency with `assert` etc. from the +// stdlib, and because recent versions of the XCTest overlay require `StaticString` +// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we +// have to use `String` instead because StaticString can't be generated from Objective-C +#if SWIFT_PACKAGE +public typealias FileString = StaticString +#else +public typealias FileString = String +#endif + +public final class SourceLocation: NSObject { + public let file: FileString + public let line: UInt + + override init() { + file = "Unknown File" + line = 0 + } + + init(file: FileString, line: UInt) { + self.file = file + self.line = line + } + + override public var description: String { + return "\(file):\(line)" + } +} diff --git a/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..7c4d273 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift @@ -0,0 +1,206 @@ +import Foundation + +internal func identityAsString(_ value: Any?) -> String { + let anyObject: AnyObject? +#if os(Linux) + anyObject = value as? AnyObject +#else + anyObject = value as AnyObject? +#endif + if let value = anyObject { + return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description + } else { + return "nil" + } +} + +internal func arrayAsString(_ items: [T], joiner: String = ", ") -> String { + return items.reduce("") { accum, item in + let prefix = (accum.isEmpty ? "" : joiner) + return accum + prefix + "\(stringify(item))" + } +} + +/// A type with a customized test output text representation. +/// +/// This textual representation is produced when values will be +/// printed in test runs, and may be useful when producing +/// error messages in custom matchers. +/// +/// - SeeAlso: `CustomDebugStringConvertible` +public protocol TestOutputStringConvertible { + var testDescription: String { get } +} + +extension Double: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension Float: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +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 { + case 1: + return NSString(format: "%0.1f", self.doubleValue).description + case 2: + return NSString(format: "%0.2f", self.doubleValue).description + case 3: + return NSString(format: "%0.3f", self.doubleValue).description + default: + return NSString(format: "%0.4f", self.doubleValue).description + } + } + return self.description + } +} + +extension Array: TestOutputStringConvertible { + public var testDescription: String { + let list = self.map(Nimble.stringify).joined(separator: ", ") + return "[\(list)]" + } +} + +extension AnySequence: TestOutputStringConvertible { + public var testDescription: String { + let generator = self.makeIterator() + var strings = [String]() + var value: AnySequence.Iterator.Element? + + repeat { + value = generator.next() + if let value = value { + strings.append(stringify(value)) + } + } while value != nil + + let list = strings.joined(separator: ", ") + return "[\(list)]" + } +} + +extension NSArray: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension NSIndexSet: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension String: TestOutputStringConvertible { + public var testDescription: String { + return self + } +} + +extension Data: TestOutputStringConvertible { + public var testDescription: String { + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16) + return "Data" + #else + return "Data" + #endif + } +} + +/// +/// Returns a string appropriate for displaying in test output +/// from the provided value. +/// +/// - parameter value: A value that will show up in a test's output. +/// +/// - returns: The string that is returned can be +/// customized per type by conforming a type to the `TestOutputStringConvertible` +/// protocol. When stringifying a non-`TestOutputStringConvertible` type, this +/// function will return the value's debug description and then its +/// normal description if available and in that order. Otherwise it +/// will return the result of constructing a string from the value. +/// +/// - SeeAlso: `TestOutputStringConvertible` +public func stringify(_ value: T?) -> String { + guard let value = value else { return "nil" } + + if let value = value as? TestOutputStringConvertible { + return value.testDescription + } + + if let value = value as? CustomDebugStringConvertible { + return value.debugDescription + } + + return String(describing: value) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@objc public class NMBStringer: NSObject { + @objc public class func stringify(_ obj: Any?) -> String { + return Nimble.stringify(obj) + } +} +#endif + +// MARK: Collection Type Stringers + +/// Attempts to generate a pretty type string for a given value. If the value is of a Objective-C +/// collection type, or a subclass thereof, (e.g. `NSArray`, `NSDictionary`, etc.). +/// This function will return the type name of the root class of the class cluster for better +/// readability (e.g. `NSArray` instead of `__NSArrayI`). +/// +/// For values that don't have a type of an Objective-C collection, this function returns the +/// default type description. +/// +/// - parameter value: A value that will be used to determine a type name. +/// +/// - returns: The name of the class cluster root class for Objective-C collection types, or the +/// the `dynamicType` of the value for values of any other type. +public func prettyCollectionType(_ value: T) -> String { + switch value { + case is NSArray: + return String(describing: NSArray.self) + case is NSDictionary: + return String(describing: NSDictionary.self) + case is NSSet: + return String(describing: NSSet.self) + case is NSIndexSet: + return String(describing: NSIndexSet.self) + default: + return String(describing: value) + } +} + +/// Returns the type name for a given collection type. This overload is used by Swift +/// collection types. +/// +/// - parameter collection: A Swift `CollectionType` value. +/// +/// - returns: A string representing the `dynamicType` of the value. +public func prettyCollectionType(_ collection: T) -> String { + return String(describing: type(of: collection)) +} diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..9170541 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,389 @@ +#import + +@class NMBExpectation; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; +@protocol NMBMatcher; + + +NS_ASSUME_NONNULL_BEGIN + + +#define NIMBLE_OVERLOADABLE __attribute__((overloadable)) +#define NIMBLE_EXPORT FOUNDATION_EXPORT +#define NIMBLE_EXPORT_INLINE FOUNDATION_STATIC_INLINE + +#define NIMBLE_VALUE_OF(VAL) ({ \ + __typeof__((VAL)) val = (VAL); \ + [NSValue valueWithBytes:&val objCType:@encode(__typeof__((VAL)))]; \ +}) + +#ifdef NIMBLE_DISABLE_SHORT_SYNTAX +#define NIMBLE_SHORT(PROTO, ORIGINAL) +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) +#else +#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); } +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE NIMBLE_OVERLOADABLE PROTO { return (ORIGINAL); } +#endif + + + +#define DEFINE_NMB_EXPECT_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBExpectation *NMB_expect(TYPE(^actualBlock)(void), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(void), NSString *file, NSUInteger line); + + // overloaded dispatch for nils - expect(nil) + DEFINE_NMB_EXPECT_OVERLOAD(void*, nil) + DEFINE_NMB_EXPECT_OVERLOAD(NSRange, NIMBLE_VALUE_OF(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(float, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(double, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned char, @(actualBlock())) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_NMB_EXPECT_OVERLOAD(BOOL, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char *, @(actualBlock())) + + +#undef DEFINE_NMB_EXPECT_OVERLOAD + + + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line); + + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_equal(TYPE expectedValue) { \ + return NMB_equal((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id equal(TYPE expectedValue), NMB_equal(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_equal(__nullable id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id equal(__nullable id expectedValue), + NMB_equal(expectedValue)); + + // overloaded dispatch for nils - expect(nil) + DEFINE_OVERLOAD(void*__nullable, (id)nil) + DEFINE_OVERLOAD(NSRange, NIMBLE_VALUE_OF(expectedValue)) + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_OVERLOAD(BOOL, @(expectedValue)) + DEFINE_OVERLOAD(char *, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_haveCount(TYPE expectedValue) { \ + return NMB_haveCount((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id haveCount(TYPE expectedValue), \ + NMB_haveCount(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_haveCount(id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id haveCount(id expectedValue), + NMB_haveCount(expectedValue)); + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ + return NMB_beCloseTo((NSNumber *)(EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ + NMB_beCloseTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), + NMB_beCloseTo(expectedValue)); + + // it would be better to only overload float & double, but zero becomes ambigious + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAnInstanceOf(Class expectedClass) { + return NMB_beAnInstanceOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAKindOf(Class expectedClass) { + return NMB_beAKindOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE id beginWith(id itemElementOrSubstring) { + return NMB_beginWith(itemElementOrSubstring); +} + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThan(TYPE expectedValue) { \ + return NMB_beGreaterThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThan(NSNumber *expectedValue) { + return NMB_beGreaterThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beGreaterThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThanOrEqualTo(TYPE expectedValue), \ + NMB_beGreaterThanOrEqualTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beGreaterThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(id beIdenticalTo(id expectedInstance), + NMB_beIdenticalTo(expectedInstance)); + +NIMBLE_EXPORT id NMB_be(id expectedInstance); +NIMBLE_SHORT(id be(id expectedInstance), + NMB_be(expectedInstance)); + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThan(TYPE expectedValue) { \ + return NMB_beLessThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThan(TYPE expectedValue), \ + NMB_beLessThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThan(NSNumber *expectedValue) { + return NMB_beLessThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beLessThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThanOrEqualTo(TYPE expectedValue), \ + NMB_beLessThanOrEqualTo(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beLessThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beTruthy(void); +NIMBLE_SHORT(id beTruthy(void), + NMB_beTruthy()); + +NIMBLE_EXPORT id NMB_beFalsy(void); +NIMBLE_SHORT(id beFalsy(void), + NMB_beFalsy()); + +NIMBLE_EXPORT id NMB_beTrue(void); +NIMBLE_SHORT(id beTrue(void), + NMB_beTrue()); + +NIMBLE_EXPORT id NMB_beFalse(void); +NIMBLE_SHORT(id beFalse(void), + NMB_beFalse()); + +NIMBLE_EXPORT id NMB_beNil(void); +NIMBLE_SHORT(id beNil(void), + NMB_beNil()); + +NIMBLE_EXPORT id NMB_beEmpty(void); +NIMBLE_SHORT(id beEmpty(void), + NMB_beEmpty()); + +NIMBLE_EXPORT id 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 NMB_containElementSatisfying(BOOL(^predicate)(id)); +NIMBLE_SHORT(id containElementSatisfying(BOOL(^predicate)(id)), + NMB_containElementSatisfying(predicate)); + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(id endWith(id itemElementOrSubstring), + NMB_endWith(itemElementOrSubstring)); + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), + NMB_raiseException()); + +NIMBLE_EXPORT id NMB_match(id expectedValue); +NIMBLE_SHORT(id match(id expectedValue), + NMB_match(expectedValue)); + +NIMBLE_EXPORT id NMB_allPass(id matcher); +NIMBLE_SHORT(id allPass(id matcher), + NMB_allPass(matcher)); + +NIMBLE_EXPORT id 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 NMB_satisfyAllOfWithMatchers(id matchers); +#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__]) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__) +#endif + +// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__, +// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout +// and action arguments. See https://github.com/Quick/Quick/pull/185 for details. +typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void))); +typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void))); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line); +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +#define NMB_waitUntilTimeout NMB_waitUntilTimeoutBuilder(@(__FILE__), __LINE__) +#define NMB_waitUntil NMB_waitUntilBuilder(@(__FILE__), __LINE__) + +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define expect(...) NMB_expect(^{ return (__VA_ARGS__); }, @(__FILE__), __LINE__) +#define expectAction(BLOCK) NMB_expectAction((BLOCK), @(__FILE__), __LINE__) +#define failWithMessage(msg) NMB_failWithMessage(msg, @(__FILE__), __LINE__) +#define fail() failWithMessage(@"fail() always fails") + + +#define waitUntilTimeout NMB_waitUntilTimeout +#define waitUntil NMB_waitUntil + +#undef NIMBLE_VALUE_OF + +#endif + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..670415b --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,161 @@ +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(void), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line) { + return NMB_expect(^id{ + actualBlock(); + return nil; + }, file, line); +} + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line) { + return [NMBExpectation failWithMessage:msg file:file line:line]; +} + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass) { + return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass) { + return [NMBObjCMatcher beAKindOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001]; +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring) { + return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT id NMB_be(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beTruthy() { + return [NMBObjCMatcher beTruthyMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalsy() { + return [NMBObjCMatcher beFalsyMatcher]; +} + +NIMBLE_EXPORT id NMB_beTrue() { + return [NMBObjCMatcher beTrueMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalse() { + return [NMBObjCMatcher beFalseMatcher]; +} + +NIMBLE_EXPORT id NMB_beNil() { + return [NMBObjCMatcher beNilMatcher]; +} + +NIMBLE_EXPORT id NMB_beEmpty() { + return [NMBObjCMatcher beEmptyMatcher]; +} + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) { + NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; + + if (itemOrSubstring) { + [itemOrSubstringArray addObject:itemOrSubstring]; + + va_list args; + va_start(args, itemOrSubstring); + id next; + while ((next = va_arg(args, id))) { + [itemOrSubstringArray addObject:next]; + } + va_end(args); + } + + return [NMBObjCMatcher containMatcher:itemOrSubstringArray]; +} + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)) { + return [NMBObjCMatcher containElementSatisfyingMatcher:predicate]; +} + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring) { + return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_equal(__nullable id expectedValue) { + return [NMBObjCMatcher equalMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_haveCount(id expectedValue) { + return [NMBObjCMatcher haveCountMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_match(id expectedValue) { + return [NMBObjCMatcher matchMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_allPass(id expectedValue) { + return [NMBObjCMatcher allPassMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAnyOfMatcher:matchers]; +} + +NIMBLE_EXPORT id NMB_satisfyAllOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAllOfMatcher:matchers]; +} + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..e6e0272 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h @@ -0,0 +1,11 @@ +#import +#import + +@interface NMBExceptionCapture : NSObject + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..52684b7 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m @@ -0,0 +1,35 @@ +#import "NMBExceptionCapture.h" + +@interface NMBExceptionCapture () +@property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); +@property (nonatomic, copy) void(^ _Nullable finally)(void); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..7938bca --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h @@ -0,0 +1,18 @@ +@class NSString; + +/** + * Returns a string appropriate for displaying in test output + * from the provided value. + * + * @param anyObject A value that will show up in a test's output. + * + * @return The string that is returned can be + * customized per type by conforming a type to the `TestOutputStringConvertible` + * protocol. When stringifying a non-`TestOutputStringConvertible` type, this + * function will return the value's debug description and then its + * normal description if available and in that order. Otherwise it + * will return the result of constructing a string from the value. + * + * @see `TestOutputStringConvertible` + */ +extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..31a80d6 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,11 @@ +#import "NMBStringify.h" + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..fa5030a --- /dev/null +++ b/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -0,0 +1,83 @@ +#import +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +#pragma mark - Method Swizzling + +/// Swaps the implementations between two instance methods. +/// +/// @param class The class containing `originalSelector`. +/// @param originalSelector Original method to replace. +/// @param replacementSelector Replacement method. +void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method replacementMethod = class_getInstanceMethod(class, replacementSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(replacementMethod), + method_getTypeEncoding(replacementMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + replacementSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, replacementMethod); + } +} + +#pragma mark - Private + +@interface XCTestObservationCenter (Private) +- (void)_addLegacyTestObserver:(id)observer; +@end + +@implementation XCTestObservationCenter (Register) + +/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary +/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early +/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. +/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, +/// falling back to registering after the first normal observer if this private method ever changes. ++ (void)load { + if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { + // Swizzle -_addLegacyTestObserver: + swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); + } else { + // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented + swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); + } +} + +#pragma mark - Replacement Methods + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +- (void)NMB_original__addLegacyTestObserver:(id)observer { + [self NMB_original__addLegacyTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) +- (void)NMB_original_addTestObserver:(id)observer { + [self NMB_original_addTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml b/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml new file mode 100644 index 0000000..f003326 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/.swiftlint.yml @@ -0,0 +1,2 @@ +disabled_rules: + - line_length diff --git a/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift @@ -0,0 +1,37 @@ +import XCTest +@testable import NimbleTests + +// This is the entry point for NimbleTests on Linux + +XCTMain([ + testCase(AsyncTest.allTests), + testCase(SynchronousTest.allTests), + testCase(UserDescriptionTest.allTests), + + // Matchers + testCase(AllPassTest.allTests), + testCase(BeAKindOfSwiftTest.allTests), + testCase(BeAnInstanceOfTest.allTests), + testCase(BeCloseToTest.allTests), + testCase(BeginWithTest.allTests), + testCase(BeGreaterThanOrEqualToTest.allTests), + testCase(BeGreaterThanTest.allTests), + testCase(BeIdenticalToObjectTest.allTests), + testCase(BeIdenticalToTest.allTests), + testCase(BeLessThanOrEqualToTest.allTests), + testCase(BeLessThanTest.allTests), + testCase(BeTruthyTest.allTests), + testCase(BeTrueTest.allTests), + testCase(BeFalsyTest.allTests), + testCase(BeFalseTest.allTests), + testCase(BeNilTest.allTests), + testCase(ContainTest.allTests), + testCase(EndWithTest.allTests), + testCase(EqualTest.allTests), + testCase(HaveCountTest.allTests), + testCase(MatchTest.allTests), + // testCase(RaisesExceptionTest.allTests), + testCase(ThrowErrorTest.allTests), + testCase(SatisfyAnyOfTest.allTests), + testCase(PostNotificationTest.allTests), +]) diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..c44b9e6 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,257 @@ +import Dispatch +import Foundation +import XCTest +import Nimble + +final class AsyncTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AsyncTest) -> () throws -> Void)] { + return [ + ("testToEventuallyPositiveMatches", testToEventuallyPositiveMatches), + ("testToEventuallyNegativeMatches", testToEventuallyNegativeMatches), + ("testWaitUntilWithCustomDefaultsTimeout", testWaitUntilWithCustomDefaultsTimeout), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ("testSubjectUnderTestIsReleasedFromMemory", testSubjectUnderTestIsReleasedFromMemory), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testToEventuallyPositiveMatches() { + var value = 0 + deferToMainQueue { value = 1 } + expect { value }.toEventually(equal(1)) + + deferToMainQueue { value = 0 } + expect { value }.toEventuallyNot(equal(1)) + } + + func testToEventuallyNegativeMatches() { + let value = 0 + failsWithErrorMessage("expected to eventually not equal <0>, got <0>") { + expect { value }.toEventuallyNot(equal(0)) + } + failsWithErrorMessage("expected to eventually equal <1>, got <0>") { + expect { value }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventuallyNot(equal(0)) + } + } + + func testToEventuallyWithCustomDefaultTimeout() { + AsyncDefaults.Timeout = 2 + defer { + AsyncDefaults.Timeout = 1 + } + + var value = 0 + + let sleepThenSetValueTo: (Int) -> Void = { newValue in + Thread.sleep(forTimeInterval: 1.1) + value = newValue + } + + var asyncOperation: () -> Void = { sleepThenSetValueTo(1) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventually(equal(1)) + + asyncOperation = { sleepThenSetValueTo(0) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventuallyNot(equal(1)) + } + + func testWaitUntilWithCustomDefaultsTimeout() { + AsyncDefaults.Timeout = 5 + defer { + AsyncDefaults.Timeout = 1 + } + waitUntil { done in + Thread.sleep(forTimeInterval: 4.8) + done() + } + } + + func testWaitUntilPositiveMatches() { + waitUntil { done in + done() + } + waitUntil { done in + deferToMainQueue { + done() + } + } + } + + func testWaitUntilTimesOutIfNotCalled() { + failsWithErrorMessage("Waited more than 1.0 second") { + waitUntil(timeout: 1) { _ in return } + } + } + + func testWaitUntilTimesOutWhenExceedingItsTime() { + var waiting = true + failsWithErrorMessage("Waited more than 0.01 seconds") { + waitUntil(timeout: 0.01) { done in + let asyncOperation: () -> Void = { + Thread.sleep(forTimeInterval: 0.1) + done() + waiting = false + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + } + } + + // "clear" runloop to ensure this test doesn't poison other tests + repeat { + RunLoop.main.run(until: Date().addingTimeInterval(0.2)) + } while(waiting) + } + + func testWaitUntilNegativeMatches() { + failsWithErrorMessage("expected to equal <2>, got <1>") { + waitUntil { done in + Thread.sleep(forTimeInterval: 0.1) + expect(1).to(equal(2)) + done() + } + } + } + + func testWaitUntilDetectsStalledMainThreadActivity() { + let msg = "-waitUntil() timed out but was unable to run the timeout handler because the main thread is unresponsive (0.5 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." + failsWithErrorMessage(msg) { + waitUntil(timeout: 1) { done in + Thread.sleep(forTimeInterval: 5.0) + done() + } + } + } + + func testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed() { + // Currently we are unable to catch Objective-C exceptions when built by the Swift Package Manager +#if !SWIFT_PACKAGE + let referenceLine = #line + 9 + var msg = "Unexpected exception raised: Nested async expectations are not allowed " + msg += "to avoid creating flaky tests." + msg += "\n\n" + msg += "The call to\n\t" + msg += "expect(...).toEventually(...) at \(#file):\(referenceLine + 7)\n" + msg += "triggered this exception because\n\t" + msg += "waitUntil(...) at \(#file):\(referenceLine + 1)\n" + msg += "is currently managing the main run loop." + failsWithErrorMessage(msg) { // reference line + waitUntil(timeout: 2.0) { done in + var protected: Int = 0 + DispatchQueue.main.async { + protected = 1 + } + + expect(protected).toEventually(equal(1)) + done() + } + } +#endif + } + + func testWaitUntilErrorsIfDoneIsCalledMultipleTimes() { + failsWithErrorMessage("waitUntil(..) expects its completion closure to be only called once") { + waitUntil { done in + deferToMainQueue { + done() + done() + } + } + } + } + + func testWaitUntilMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + waitUntil { done in done() } + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + func testToEventuallyMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + expect(1).toEventually(equal(2)) + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + final class ClassUnderTest { + var deinitCalled: (() -> Void)? + var count = 0 + deinit { deinitCalled?() } + } + + func testSubjectUnderTestIsReleasedFromMemory() { + var subject: ClassUnderTest? = ClassUnderTest() + + if let sub = subject { + expect(sub.count).toEventually(equal(0), timeout: 0.1) + expect(sub.count).toEventuallyNot(equal(1), timeout: 0.1) + } + + waitUntil(timeout: 0.5) { done in + subject?.deinitCalled = { + done() + } + + deferToMainQueue { subject = nil } + } + } + +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift @@ -0,0 +1,7 @@ +import Foundation + +class ObjectWithLazyProperty { + init() {} + lazy var value: String = "hello" + lazy var anotherValue: String = { return "world" }() +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..08a67c6 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +extension XCTestCaseProvider { + var allTestNames: [String] { + return type(of: self).allTests.map({ name, _ in + return name + }) + } +} + +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } +} + +extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..8c042d7 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,100 @@ +import Dispatch +import Foundation +@testable import Nimble +import XCTest + +func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () throws -> Void) { + var filePath = file + var lineNumber = line + + let recorder = AssertionRecorder() + withAssertionHandler(recorder, closure: closure) + + for msg in messages { + var lastFailure: AssertionRecord? + var foundFailureMessage = false + + for assertion in recorder.assertions where assertion.message.stringValue == msg && !assertion.success { + lastFailure = assertion + foundFailureMessage = true + break + } + + if foundFailureMessage { + continue + } + + if preferOriginalSourceLocation { + if let failure = lastFailure { + filePath = failure.location.file + lineNumber = failure.location.line + } + } + + let message: String + if let lastFailure = lastFailure { + message = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\"" + } else { + let knownFailures = recorder.assertions.filter { !$0.success }.map { $0.message.stringValue } + let knownFailuresJoined = knownFailures.joined(separator: ", ") + message = "Expected error message (\(msg)), got (\(knownFailuresJoined))\n\nAssertions Received:\n\(recorder.assertions)" + } + NimbleAssertionHandler.assert(false, + message: FailureMessage(stringValue: message), + location: SourceLocation(file: filePath, line: lineNumber)) + } +} + +func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () -> Void) { + return failsWithErrorMessage( + [message], + file: file, + line: line, + preferOriginalSourceLocation: preferOriginalSourceLocation, + closure: closure + ) +} + +func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () -> Void) { + failsWithErrorMessage("\(message) (use beNil() to match nils)", file: file, line: line, preferOriginalSourceLocation: preferOriginalSourceLocation, closure: closure) +} + +func deferToMainQueue(action: @escaping () -> Void) { + DispatchQueue.main.async { + Thread.sleep(forTimeInterval: 0.01) + action() + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +public class NimbleHelper: NSObject { + @objc public class func expectFailureMessage(_ message: NSString, block: () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessages(_ messages: [NSString], block: () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(messages.map({String(describing: $0)}), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessageForNil(_ message: NSString, block: () -> Void, file: FileString, line: UInt) { + failsWithErrorMessageForNil(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } +} +#endif + +extension Date { + init(dateTimeString: String) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + let date = dateFormatter.date(from: dateTimeString)! + self.init(timeInterval: 0, since: date) + } +} + +extension NSDate { + convenience init(dateTimeString: String) { + let date = Date(dateTimeString: dateTimeString) + self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate) + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift @@ -0,0 +1,9 @@ +import Foundation + +#if os(Linux) + extension NSNotification.Name { + init(_ rawValue: String) { + self.init(rawValue: rawValue) + } + } +#endif diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift @@ -0,0 +1,126 @@ +import XCTest +import Nimble + +/// Add operators to `Optional` for conforming `Comparable` that removed in Swift 3.0 +extension Optional where Wrapped: Comparable { + static func < (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } + } + + static func > (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } + } + + static func <= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l <= r + default: + return !(rhs < lhs) + } + } + + static func >= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } + } +} + +final class AllPassTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AllPassTest) -> () throws -> Void)] { + return [ + ("testAllPassArray", testAllPassArray), + ("testAllPassMatcher", testAllPassMatcher), + ("testAllPassCollectionsWithOptionalsDontWork", testAllPassCollectionsWithOptionalsDontWork), + ("testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer", testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer), + ("testAllPassSet", testAllPassSet), + ("testAllPassWithNilAsExpectedValue", testAllPassWithNilAsExpectedValue), + ] + } + + func testAllPassArray() { + expect([1, 2, 3, 4]).to(allPass({$0 < 5})) + expect([1, 2, 3, 4]).toNot(allPass({$0 > 5})) + + failsWithErrorMessage( + "expected to all pass a condition, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass({$0 < 3})) + } + failsWithErrorMessage("expected to not all pass a condition") { + expect([1, 2, 3, 4]).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage( + "expected to all be something, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass("be something", {$0 < 3})) + } + failsWithErrorMessage("expected to not all be something") { + expect([1, 2, 3, 4]).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassMatcher() { + expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) + expect([1, 2, 3, 4]).toNot(allPass(beGreaterThan(5))) + + failsWithErrorMessage( + "expected to all be less than <3>, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass(beLessThan(3))) + } + failsWithErrorMessage("expected to not all be less than <5>") { + expect([1, 2, 3, 4]).toNot(allPass(beLessThan(5))) + } + } + + func testAllPassCollectionsWithOptionalsDontWork() { + failsWithErrorMessage("expected to all be nil, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass(beNil())) + } + failsWithErrorMessage("expected to all pass a condition, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass({$0 == nil})) + } + } + + func testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer() { + expect([nil, nil, nil] as [Int?]).to(allPass({$0! == nil})) + expect([nil, 1, nil] as [Int?]).toNot(allPass({$0! == nil})) + expect([1, 1, 1] as [Int?]).to(allPass({$0! == 1})) + expect([1, 1, nil] as [Int?]).toNot(allPass({$0! == 1})) + expect([1, 2, 3] as [Int?]).to(allPass({$0! < 4})) + expect([1, 2, 3] as [Int?]).toNot(allPass({$0! < 3})) + expect([1, 2, nil] as [Int?]).to(allPass({$0! < 3})) + } + + func testAllPassSet() { + expect(Set([1, 2, 3, 4])).to(allPass({$0 < 5})) + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 > 5})) + + failsWithErrorMessage("expected to not all pass a condition") { + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage("expected to not all be something") { + expect(Set([1, 2, 3, 4])).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassWithNilAsExpectedValue() { + failsWithErrorMessageForNil("expected to all pass") { + expect(nil as [Int]?).to(allPass(beLessThan(5))) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..bb9041b --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +private class TestNull: NSNull {} +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfSwiftTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + enum TestEnum { + case one, two + } + + func testPositiveMatch() { + expect(1).to(beAKindOf(Int.self)) + expect(1).toNot(beAKindOf(String.self)) + expect("turtle string").to(beAKindOf(String.self)) + expect("turtle string").toNot(beAKindOf(TestClassConformingToProtocol.self)) + + expect(TestEnum.one).to(beAKindOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAKindOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).to(beAKindOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAKindOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAKindOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).to(beAKindOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAKindOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessage("expected to not be a kind of Int, got ") { + expect(1).toNot(beAKindOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to not be a kind of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).toNot(beAKindOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be a kind of String, got ") { + expect(1).to(beAKindOf(String.self)) + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfObjCTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + func testPositiveMatch() { + expect(TestNull()).to(beAKindOf(NSNull.self)) + expect(NSObject()).to(beAKindOf(NSObject.self)) + expect(NSNumber(value: 1)).toNot(beAKindOf(NSDate.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be a kind of NSNull, got ") { + expect(nil as NSNull?).toNot(beAKindOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be a kind of NSString, got ") { + expect(nil as NSString?).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to be a kind of NSString, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to not be a kind of NSNumber, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).toNot(beAKindOf(NSNumber.self)) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..aeea28a --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAnInstanceOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAnInstanceOfTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testPositiveMatchSwiftTypes", testPositiveMatchSwiftTypes), + ("testFailureMessages", testFailureMessages), + ("testFailureMessagesSwiftTypes", testFailureMessagesSwiftTypes), + ] + } + + func testPositiveMatch() { + expect(NSNull()).to(beAnInstanceOf(NSNull.self)) + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(NSDate.self)) + } + + enum TestEnum { + case one, two + } + + func testPositiveMatchSwiftTypes() { + expect(1).to(beAnInstanceOf(Int.self)) + expect("test").to(beAnInstanceOf(String.self)) + + expect(TestEnum.one).to(beAnInstanceOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAnInstanceOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAnInstanceOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be an instance of NSNull, got ") { + expect(nil as NSNull?).toNot(beAnInstanceOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be an instance of NSString, got ") { + expect(nil as NSString?).to(beAnInstanceOf(NSString.self)) + } +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let numberTypeName = "__NSCFNumber" +#else + let numberTypeName = "NSNumber" +#endif + failsWithErrorMessage("expected to be an instance of NSString, got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).to(beAnInstanceOf(NSString.self)) + } + failsWithErrorMessage("expected to not be an instance of \(numberTypeName), got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(type(of: NSNumber(value: 1)))) + } + } + + func testFailureMessagesSwiftTypes() { + failsWithErrorMessage("expected to not be an instance of Int, got ") { + expect(1).toNot(beAnInstanceOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to be an instance of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).to(beAnInstanceOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be an instance of String, got ") { + expect(1).to(beAnInstanceOf(String.self)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..cb7a3ec --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift @@ -0,0 +1,160 @@ +import Foundation +import XCTest +import Nimble + +final class BeCloseToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeCloseToTest) -> () throws -> Void)] { + return [ + ("testBeCloseTo", testBeCloseTo), + ("testBeCloseToWithin", testBeCloseToWithin), + ("testBeCloseToWithNSNumber", testBeCloseToWithNSNumber), + ("testBeCloseToWithDate", testBeCloseToWithDate), + ("testBeCloseToWithNSDate", testBeCloseToWithNSDate), + ("testBeCloseToOperator", testBeCloseToOperator), + ("testBeCloseToWithinOperator", testBeCloseToWithinOperator), + ("testPlusMinusOperator", testPlusMinusOperator), + ("testBeCloseToOperatorWithDate", testBeCloseToOperatorWithDate), + ("testBeCloseToWithinOperatorWithDate", testBeCloseToWithinOperatorWithDate), + ("testPlusMinusOperatorWithDate", testPlusMinusOperatorWithDate), + ("testBeCloseToArray", testBeCloseToArray), + ("testBeCloseToWithCGFloat", testBeCloseToWithCGFloat), + ] + } + + func testBeCloseTo() { + expect(1.2).to(beCloseTo(1.2001)) + expect(1.2 as CDouble).to(beCloseTo(1.2001)) + expect(1.2 as Float).to(beCloseTo(1.2001)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 0.0001), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001)) + } + } + + func testBeCloseToWithin() { + expect(1.2).to(beCloseTo(9.300, within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithNSNumber() { + expect(NSNumber(value: 1.2)).to(beCloseTo(9.300, within: 10)) + expect(NSNumber(value: 1.2)).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + expect(1.2).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithCGFloat() { + expect(CGFloat(1.2)).to(beCloseTo(1.2001)) + expect(CGFloat(1.2)).to(beCloseTo(CGFloat(1.2001))) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(Date(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToWithNSDate() { + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(NSDate(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = NSDate(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToOperator() { + expect(1.2) ≈ 1.2001 + expect(1.2 as CDouble) ≈ 1.2001 + + failsWithErrorMessage("expected to be close to <1.2002> (within 0.0001), got <1.2>") { + expect(1.2) ≈ 1.2002 + } + } + + func testBeCloseToWithinOperator() { + expect(1.2) ≈ (9.300, 10) + expect(1.2) == (9.300, 10) + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ (1.0, 0.1) + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == (1.0, 0.1) + } + } + + func testPlusMinusOperator() { + expect(1.2) ≈ 9.300 ± 10 + expect(1.2) == 9.300 ± 10 + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ 1.0 ± 0.1 + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == 1.0 ± 0.1 + } + } + + func testBeCloseToOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:00") + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.0001), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate + } + } + + func testBeCloseToWithinOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (expectedDate, 0.004) + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (expectedDate, 0.004) + } + } + + func testPlusMinusOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate ± 0.004 + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == expectedDate ± 0.004 + } + } + + func testBeCloseToArray() { + expect([0.0, 1.1, 2.2]) ≈ [0.0001, 1.1001, 2.2001] + expect([0.0, 1.1, 2.2]).to(beCloseTo([0.1, 1.2, 2.3], within: 0.1)) + + failsWithErrorMessage("expected to be close to <[0, 1]> (each within 0.0001), got <[0, 1.1]>") { + expect([0.0, 1.1]) ≈ [0.0, 1.0] + } + failsWithErrorMessage("expected to be close to <[0.2, 1.2]> (each within 0.1), got <[0, 1.1]>") { + expect([0.0, 1.1]).to(beCloseTo([0.2, 1.2], within: 0.1)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..067ddeb --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift @@ -0,0 +1,82 @@ +import Foundation +import XCTest +import Nimble + +final class BeEmptyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeEmptyTest) -> () throws -> Void)] { + return [ + ("testBeEmptyPositive", testBeEmptyPositive), + ("testBeEmptyNegative", testBeEmptyNegative), + ] + } + + func testBeEmptyPositive() { + expect([] as [Int]).to(beEmpty()) + expect([1]).toNot(beEmpty()) + + expect([] as [CInt]).to(beEmpty()) + expect([1] as [CInt]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary() as? [Int: Int]).to(beEmpty()) + expect(NSDictionary(object: 1, forKey: 1 as NSNumber) as? [Int: Int]).toNot(beEmpty()) +#endif + + expect([Int: Int]()).to(beEmpty()) + expect(["hi": 1]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray() as? [Int]).to(beEmpty()) + expect(NSArray(array: [1]) as? [Int]).toNot(beEmpty()) +#endif + + expect(NSSet()).to(beEmpty()) + expect(NSSet(array: [NSNumber(value: 1)])).toNot(beEmpty()) + + expect(NSIndexSet()).to(beEmpty()) + expect(NSIndexSet(index: 1)).toNot(beEmpty()) + + expect(NSString()).to(beEmpty()) + expect(NSString(string: "hello")).toNot(beEmpty()) + + expect("").to(beEmpty()) + expect("foo").toNot(beEmpty()) + } + + func testBeEmptyNegative() { + failsWithErrorMessageForNil("expected to be empty, got ") { + expect(nil as NSString?).to(beEmpty()) + } + failsWithErrorMessageForNil("expected to not be empty, got ") { + expect(nil as [CInt]?).toNot(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSArray()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <[1]>") { + expect([1]).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <{()}>") { + expect(NSSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <{(1)}>") { + expect(NSSet(object: NSNumber(value: 1))).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSIndexSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <(1)>") { + expect(NSIndexSet(index: 1)).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <>") { + expect("").toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got ") { + expect("foo").to(beEmpty()) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..bd73361 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testGreaterThanOrEqualTo", testGreaterThanOrEqualTo), + ("testGreaterThanOrEqualToOperator", testGreaterThanOrEqualToOperator), + ] + } + + func testGreaterThanOrEqualTo() { + expect(10).to(beGreaterThanOrEqualTo(10)) + expect(10).to(beGreaterThanOrEqualTo(2)) + expect(1).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 1)).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 2)).to(beGreaterThanOrEqualTo(NSNumber(value: 2))) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(1).to(beGreaterThanOrEqualTo(NSNumber(value: 0))) +#endif + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <0>") { + expect(0).to(beGreaterThanOrEqualTo(2)) + return + } + failsWithErrorMessage("expected to not be greater than or equal to <1>, got <1>") { + expect(1).toNot(beGreaterThanOrEqualTo(1)) + return + } + failsWithErrorMessageForNil("expected to be greater than or equal to <-2>, got ") { + expect(nil as Int?).to(beGreaterThanOrEqualTo(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than or equal to <1>, got ") { + expect(nil as Int?).toNot(beGreaterThanOrEqualTo(1)) + } + } + + func testGreaterThanOrEqualToOperator() { + expect(0) >= 0 + expect(1) >= 0 + expect(NSNumber(value: 1)) >= 1 + expect(NSNumber(value: 1)) >= NSNumber(value: 1) + expect(2.5) >= 2.5 + expect(2.5) >= 2 + expect(Float(2.5)) >= Float(2.5) + expect(Float(2.5)) >= 2 + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <1>") { + expect(1) >= 2 + return + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..9c33e4b --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanTest) -> () throws -> Void)] { + return [ + ("testGreaterThan", testGreaterThan), + ("testGreaterThanOperator", testGreaterThanOperator), + ] + } + + func testGreaterThan() { + expect(10).to(beGreaterThan(2)) + expect(1).toNot(beGreaterThan(2)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 3)).to(beGreaterThan(2)) +#else + expect(NSNumber(value: 3)).to(beGreaterThan(2 as NSNumber)) +#endif + expect(NSNumber(value: 1)).toNot(beGreaterThan(NSNumber(value: 2))) + + failsWithErrorMessage("expected to be greater than <2>, got <0>") { + expect(0).to(beGreaterThan(2)) + } + failsWithErrorMessage("expected to not be greater than <0>, got <1>") { + expect(1).toNot(beGreaterThan(0)) + } + failsWithErrorMessageForNil("expected to be greater than <-2>, got ") { + expect(nil as Int?).to(beGreaterThan(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than <0>, got ") { + expect(nil as Int?).toNot(beGreaterThan(0)) + } + } + + func testGreaterThanOperator() { + expect(1) > 0 + expect(NSNumber(value: 1)) > NSNumber(value: 0) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 1)) > 0 +#else + expect(NSNumber(value: 1)) > 0 as NSNumber +#endif + expect(2.5) > 1.5 + expect(Float(2.5)) > Float(1.5) + + failsWithErrorMessage("expected to be greater than <2>, got <1>") { + expect(1) > 2 + return + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift @@ -0,0 +1,64 @@ +import Foundation +import XCTest +import Nimble + +final class BeIdenticalToObjectTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToObjectTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testFailsOnNils", testFailsOnNils), + ("testOperators", testOperators), + ] + } + + private class BeIdenticalToObjectTester {} + private let testObjectA = BeIdenticalToObjectTester() + private let testObjectB = BeIdenticalToObjectTester() + + func testBeIdenticalToPositive() { + expect(self.testObjectA).to(beIdenticalTo(testObjectA)) + } + + func testBeIdenticalToNegative() { + expect(self.testObjectA).toNot(beIdenticalTo(testObjectB)) + } + + func testBeIdenticalToPositiveMessage() { + let message = String(describing: NSString(format: "expected to be identical to <%p>, got <%p>", + unsafeBitCast(testObjectB, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).to(beIdenticalTo(self.testObjectB)) + } + } + + func testBeIdenticalToNegativeMessage() { + let message = String(describing: NSString(format: "expected to not be identical to <%p>, got <%p>", + unsafeBitCast(testObjectA, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testFailsOnNils() { + let message1 = String(describing: NSString(format: "expected to be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message1) { + expect(nil as BeIdenticalToObjectTester?).to(beIdenticalTo(self.testObjectA)) + } + + let message2 = String(describing: NSString(format: "expected to not be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message2) { + expect(nil as BeIdenticalToObjectTester?).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testOperators() { + expect(self.testObjectA) === testObjectA + expect(self.testObjectA) !== testObjectB + } + +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..6b629b0 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift @@ -0,0 +1,68 @@ +import Foundation +import XCTest +@testable import Nimble + +final class BeIdenticalToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testOperators", testOperators), + ("testBeAlias", testBeAlias), + ] + } + + func testBeIdenticalToPositive() { + let value = NSDate() + expect(value).to(beIdenticalTo(value)) + } + + func testBeIdenticalToNegative() { + expect(NSNumber(value: 1)).toNot(beIdenticalTo(NSString(string: "yo"))) + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + } + + func testBeIdenticalToPositiveMessage() { + let num1 = NSNumber(value: 1) + let num2 = NSNumber(value: 2) + let message = "expected to be identical to \(identityAsString(num2)), got \(identityAsString(num1))" + failsWithErrorMessage(message) { + expect(num1).to(beIdenticalTo(num2)) + } + } + + func testBeIdenticalToNegativeMessage() { + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value2)), got \(identityAsString(value1))" + failsWithErrorMessage(message) { + expect(value1).toNot(beIdenticalTo(value2)) + } + } + + func testOperators() { + let value = NSDate() + expect(value) === value + expect(NSNumber(value: 1)) !== NSNumber(value: 2) + } + + func testBeAlias() { + let value = NSDate() + expect(value).to(be(value)) + expect(NSNumber(value: 1)).toNot(be(NSString(string: "turtles"))) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect([1]).toNot(be([1])) + #else + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + #endif + + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value1)), got \(identityAsString(value2))" + failsWithErrorMessage(message) { + expect(value1).toNot(be(value2)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..428ace4 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testLessThanOrEqualTo", testLessThanOrEqualTo), + ("testLessThanOrEqualToOperator", testLessThanOrEqualToOperator), + ] + } + + func testLessThanOrEqualTo() { + expect(10).to(beLessThanOrEqualTo(10)) + expect(2).to(beLessThanOrEqualTo(10)) + expect(2).toNot(beLessThanOrEqualTo(1)) + + expect(NSNumber(value: 2)).to(beLessThanOrEqualTo(10)) + expect(NSNumber(value: 2)).toNot(beLessThanOrEqualTo(1)) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(2).to(beLessThanOrEqualTo(NSNumber(value: 10))) + expect(2).toNot(beLessThanOrEqualTo(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than or equal to <0>, got <2>") { + expect(2).to(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessage("expected to not be less than or equal to <0>, got <0>") { + expect(0).toNot(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessageForNil("expected to be less than or equal to <2>, got ") { + expect(nil as Int?).to(beLessThanOrEqualTo(2)) + return + } + failsWithErrorMessageForNil("expected to not be less than or equal to <-2>, got ") { + expect(nil as Int?).toNot(beLessThanOrEqualTo(-2)) + return + } + } + + func testLessThanOrEqualToOperator() { + expect(0) <= 1 + expect(1) <= 1 + + failsWithErrorMessage("expected to be less than or equal to <1>, got <2>") { + expect(2) <= 1 + return + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..90ba1b9 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift @@ -0,0 +1,57 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanTest) -> () throws -> Void)] { + return [ + ("testLessThan", testLessThan), + ("testLessThanOperator", testLessThanOperator), + ] + } + + func testLessThan() { + expect(2).to(beLessThan(10)) + expect(2).toNot(beLessThan(1)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 2)).to(beLessThan(10)) + expect(NSNumber(value: 2)).toNot(beLessThan(1)) + + expect(2).to(beLessThan(NSNumber(value: 10))) + expect(2).toNot(beLessThan(NSNumber(value: 1))) +#else + expect(NSNumber(value: 2)).to(beLessThan(10 as NSNumber)) + expect(NSNumber(value: 2)).toNot(beLessThan(1 as NSNumber)) + + expect(2 as NSNumber).to(beLessThan(NSNumber(value: 10))) + expect(2 as NSNumber).toNot(beLessThan(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than <0>, got <2>") { + expect(2).to(beLessThan(0)) + } + failsWithErrorMessage("expected to not be less than <1>, got <0>") { + expect(0).toNot(beLessThan(1)) + } + + failsWithErrorMessageForNil("expected to be less than <2>, got ") { + expect(nil as Int?).to(beLessThan(2)) + } + failsWithErrorMessageForNil("expected to not be less than <-1>, got ") { + expect(nil as Int?).toNot(beLessThan(-1)) + } + } + + func testLessThanOperator() { + expect(0) < 1 +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 0)) < 1 +#else + expect(NSNumber(value: 0)) < 1 as NSNumber +#endif + failsWithErrorMessage("expected to be less than <1>, got <2>") { + expect(2) < 1 + return + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift @@ -0,0 +1,270 @@ +import XCTest +import Nimble +import Foundation + +enum ConvertsToBool: ExpressibleByBooleanLiteral, CustomStringConvertible { + case trueLike, falseLike + + typealias BooleanLiteralType = Bool + + init(booleanLiteral value: Bool) { + switch value { + case true: self = .trueLike + case false: self = .falseLike + } + } + + var boolValue: Bool { + switch self { + case .trueLike: return true + case .falseLike: return false + } + } + + var description: String { + switch self { + case .trueLike: return "TrueLike" + case .falseLike: return "FalseLike" + } + } +} + +final class BeTruthyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTruthyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNonNilTypes", testShouldMatchNonNilTypes), + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchNilTypes", testShouldNotMatchNilTypes), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ("testShouldMatchBoolConvertibleTypesThatConvertToTrue", testShouldMatchBoolConvertibleTypesThatConvertToTrue), + ("testShouldNotMatchBoolConvertibleTypesThatConvertToFalse", testShouldNotMatchBoolConvertibleTypesThatConvertToFalse), + ] + } + + func testShouldMatchNonNilTypes() { + expect(true as Bool?).to(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).to(beTruthy()) + expect(1 as UInt8?).to(beTruthy()) + expect(1 as Int16?).to(beTruthy()) + expect(1 as UInt16?).to(beTruthy()) + expect(1 as Int32?).to(beTruthy()) + expect(1 as UInt32?).to(beTruthy()) + expect(1 as Int64?).to(beTruthy()) + expect(1 as UInt64?).to(beTruthy()) + expect(1 as Float?).to(beTruthy()) + expect(1 as Double?).to(beTruthy()) + expect(1 as Int?).to(beTruthy()) + expect(1 as UInt?).to(beTruthy()) + } + + func testShouldMatchTrue() { + expect(true).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(true).toNot(beTruthy()) + } + } + + func testShouldNotMatchNilTypes() { + expect(false as Bool?).toNot(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).toNot(beTruthy()) + expect(nil as Int8?).toNot(beTruthy()) + expect(nil as UInt8?).toNot(beTruthy()) + expect(nil as Int16?).toNot(beTruthy()) + expect(nil as UInt16?).toNot(beTruthy()) + expect(nil as Int32?).toNot(beTruthy()) + expect(nil as UInt32?).toNot(beTruthy()) + expect(nil as Int64?).toNot(beTruthy()) + expect(nil as UInt64?).toNot(beTruthy()) + expect(nil as Float?).toNot(beTruthy()) + expect(nil as Double?).toNot(beTruthy()) + expect(nil as Int?).toNot(beTruthy()) + expect(nil as UInt?).toNot(beTruthy()) + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(false).to(beTruthy()) + } + } + + func testShouldNotMatchNilBools() { + expect(nil as Bool?).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(nil as Bool?).to(beTruthy()) + } + } + + func testShouldMatchBoolConvertibleTypesThatConvertToTrue() { + expect(ConvertsToBool.trueLike).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(ConvertsToBool.trueLike).toNot(beTruthy()) + } + } + + func testShouldNotMatchBoolConvertibleTypesThatConvertToFalse() { + expect(ConvertsToBool.falseLike).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(ConvertsToBool.falseLike).to(beTruthy()) + } + } +} + +final class BeTrueTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTrueTest) -> () throws -> Void)] { + return [ + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldMatchTrue() { + expect(true).to(beTrue()) + + failsWithErrorMessage("expected to not be true, got ") { + expect(true).toNot(beTrue()) + } + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTrue()) + + failsWithErrorMessage("expected to be true, got ") { + expect(false).to(beTrue()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to not be true, got ") { + expect(nil as Bool?).toNot(beTrue()) + } + + failsWithErrorMessageForNil("expected to be true, got ") { + expect(nil as Bool?).to(beTrue()) + } + } +} + +final class BeFalsyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalsyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNilTypes", testShouldMatchNilTypes), + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldNotMatchNonNilTypes", testShouldNotMatchNonNilTypes), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldMatchNilBools", testShouldMatchNilBools), + ] + } + + func testShouldMatchNilTypes() { + expect(false as Bool?).to(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).to(beFalsy()) + expect(nil as Int8?).to(beFalsy()) + expect(nil as UInt8?).to(beFalsy()) + expect(nil as Int16?).to(beFalsy()) + expect(nil as UInt16?).to(beFalsy()) + expect(nil as Int32?).to(beFalsy()) + expect(nil as UInt32?).to(beFalsy()) + expect(nil as Int64?).to(beFalsy()) + expect(nil as UInt64?).to(beFalsy()) + expect(nil as Float?).to(beFalsy()) + expect(nil as Double?).to(beFalsy()) + expect(nil as Int?).to(beFalsy()) + expect(nil as UInt?).to(beFalsy()) + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalsy()) + + failsWithErrorMessage("expected to be falsy, got ") { + expect(true).to(beFalsy()) + } + } + + func testShouldNotMatchNonNilTypes() { + expect(true as Bool?).toNot(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).toNot(beFalsy()) + expect(1 as UInt8?).toNot(beFalsy()) + expect(1 as Int16?).toNot(beFalsy()) + expect(1 as UInt16?).toNot(beFalsy()) + expect(1 as Int32?).toNot(beFalsy()) + expect(1 as UInt32?).toNot(beFalsy()) + expect(1 as Int64?).toNot(beFalsy()) + expect(1 as UInt64?).toNot(beFalsy()) + expect(1 as Float?).toNot(beFalsy()) + expect(1 as Double?).toNot(beFalsy()) + expect(1 as Int?).toNot(beFalsy()) + expect(1 as UInt?).toNot(beFalsy()) + } + + func testShouldMatchFalse() { + expect(false).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(false).toNot(beFalsy()) + } + } + + func testShouldMatchNilBools() { + expect(nil as Bool?).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(nil as Bool?).toNot(beFalsy()) + } + } +} + +final class BeFalseTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalseTest) -> () throws -> Void)] { + return [ + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalse()) + + failsWithErrorMessage("expected to be false, got ") { + expect(true).to(beFalse()) + } + } + + func testShouldMatchFalse() { + expect(false).to(beFalse()) + + failsWithErrorMessage("expected to not be false, got ") { + expect(false).toNot(beFalse()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to be false, got ") { + expect(nil as Bool?).to(beFalse()) + } + + failsWithErrorMessageForNil("expected to not be false, got ") { + expect(nil as Bool?).toNot(beFalse()) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift @@ -0,0 +1,28 @@ +import XCTest +import Nimble + +final class BeNilTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeNilTest) -> () throws -> Void)] { + return [ + ("testBeNil", testBeNil), + ] + } + + func producesNil() -> [Int]? { + return nil + } + + func testBeNil() { + expect(nil as Int?).to(beNil()) + expect(1 as Int?).toNot(beNil()) + expect(self.producesNil()).to(beNil()) + + failsWithErrorMessage("expected to not be nil, got ") { + expect(nil as Int?).toNot(beNil()) + } + + failsWithErrorMessage("expected to be nil, got <1>") { + expect(1 as Int?).to(beNil()) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift @@ -0,0 +1,32 @@ +import XCTest +import Nimble + +final class BeVoidTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeVoidTest) -> () throws -> Void)] { + return [ + ("testBeVoid", testBeVoid), + ] + } + + func testBeVoid() { + expect(()).to(beVoid()) + expect(() as ()?).to(beVoid()) + expect(nil as ()?).toNot(beVoid()) + + expect(()) == () + expect(() as ()?) == () + expect(nil as ()?) != () + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(()).toNot(beVoid()) + } + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(() as ()?).toNot(beVoid()) + } + + failsWithErrorMessage("expected to be void, got ") { + expect(nil as ()?).to(beVoid()) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..276c7d0 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeginWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeginWithTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testNegativeMatches", testNegativeMatches), + ] + } + + func testPositiveMatches() { + expect([1, 2, 3]).to(beginWith(1)) + expect([1, 2, 3]).toNot(beginWith(2)) + + expect("foobar").to(beginWith("foo")) + expect("foobar").toNot(beginWith("oo")) + + expect("foobarfoo").to(beginWith("foo")) + + expect(NSString(string: "foobar").description).to(beginWith("foo")) + expect(NSString(string: "foobar").description).toNot(beginWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(beginWith("a")) + expect(NSArray(array: ["a", "b"])).toNot(beginWith("b")) +#endif + } + + func testNegativeMatches() { + failsWithErrorMessageForNil("expected to begin with , got ") { + expect(nil as NSArray?).to(beginWith(NSString(string: "b"))) + } + failsWithErrorMessageForNil("expected to not begin with , got ") { + expect(nil as NSArray?).toNot(beginWith(NSString(string: "b"))) + } + + failsWithErrorMessage("expected to begin with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(beginWith(2)) + } + failsWithErrorMessage("expected to not begin with <1>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(beginWith(1)) + } + failsWithErrorMessage("expected to begin with , got ") { + expect("batman").to(beginWith("atm")) + } + failsWithErrorMessage("expected to not begin with , got ") { + expect("batman").toNot(beginWith("bat")) + } + } + +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift @@ -0,0 +1,86 @@ +import Foundation +import XCTest +import Nimble + +final class ContainElementSatisfyingTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainElementSatisfyingTest) -> () throws -> Void)] { + return [ + ("testContainElementSatisfying", testContainElementSatisfying), + ("testContainElementSatisfyingDefaultErrorMessage", testContainElementSatisfyingDefaultErrorMessage), + ("testContainElementSatisfyingSpecificErrorMessage", testContainElementSatisfyingSpecificErrorMessage), + ("testContainElementSatisfyingNegativeCase", + testContainElementSatisfyingNegativeCase), + ("testContainElementSatisfyingNegativeCaseDefaultErrorMessage", + testContainElementSatisfyingNegativeCaseDefaultErrorMessage), + ("testContainElementSatisfyingNegativeCaseSpecificErrorMessage", + testContainElementSatisfyingNegativeCaseSpecificErrorMessage), + ] + } + + func testContainElementSatisfying() { + var orderIndifferentArray = [1, 2, 3] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + + orderIndifferentArray = [3, 1, 2] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + } + + func testContainElementSatisfyingDefaultErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + })) + } + } + + func testContainElementSatisfyingSpecificErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection equal to 4") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + }, "equal to 4")) + } + } + + func testContainElementSatisfyingNegativeCase() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "armadillos" + })) + } + + func testContainElementSatisfyingNegativeCaseDefaultErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + })) + } + } + + func testContainElementSatisfyingNegativeCaseSpecificErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection equal to 'kittens'") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + }, "equal to 'kittens'")) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..1d8a1eb --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift @@ -0,0 +1,95 @@ +import Foundation +import XCTest +import Nimble + +final class ContainTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainTest) -> () throws -> Void)] { + return [ + ("testContain", testContain), + ("testContainSubstring", testContainSubstring), + ("testContainObjCSubstring", testContainObjCSubstring), + ("testVariadicArguments", testVariadicArguments), + ("testCollectionArguments", testCollectionArguments), + ] + } + + func testContain() { + expect([1, 2, 3]).to(contain(1)) + expect([1, 2, 3] as [CInt]).to(contain(1 as CInt)) + expect([1, 2, 3] as [CInt]).toNot(contain(4 as CInt)) + expect(["foo", "bar", "baz"]).to(contain("baz")) + expect([1, 2, 3]).toNot(contain(4)) + expect(["foo", "bar", "baz"]).toNot(contain("ba")) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a"])).to(contain(NSString(string: "a"))) + expect(NSArray(array: ["a"])).toNot(contain(NSString(string: "b"))) + expect(NSArray(object: 1) as NSArray?).to(contain(1)) +#endif + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b")) + } + + failsWithErrorMessageForNil("expected to contain , got ") { + expect(nil as [String]?).to(contain("bar")) + } + failsWithErrorMessageForNil("expected to not contain , got ") { + expect(nil as [String]?).toNot(contain("b")) + } + } + + func testContainSubstring() { + expect("foo").to(contain("o")) + expect("foo").to(contain("oo")) + expect("foo").toNot(contain("z")) + expect("foo").toNot(contain("zz")) + + failsWithErrorMessage("expected to contain , got ") { + expect("foo").to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got ") { + expect("foo").toNot(contain("oo")) + } + } + + func testContainObjCSubstring() { + let str = NSString(string: "foo") + expect(str).to(contain(NSString(string: "o"))) + expect(str).to(contain(NSString(string: "oo"))) + expect(str).toNot(contain(NSString(string: "z"))) + expect(str).toNot(contain(NSString(string: "zz"))) + } + + func testVariadicArguments() { + expect([1, 2, 3]).to(contain(1, 2)) + expect([1, 2, 3]).toNot(contain(1, 4)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("a", "bar")) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b", "a")) + } + } + + func testCollectionArguments() { + expect([1, 2, 3]).to(contain([1, 2])) + expect([1, 2, 3]).toNot(contain([1, 4])) + + let collection = Array(1...10) + let slice = Array(collection[3...5]) + expect(collection).to(contain(slice)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain(["a", "bar"])) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain(["b", "a"])) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..30e3b26 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift @@ -0,0 +1,56 @@ +import Foundation +import XCTest +import Nimble + +final class EndWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EndWithTest) -> () throws -> Void)] { + return [ + ("testEndWithPositives", testEndWithPositives), + ("testEndWithNegatives", testEndWithNegatives), + ] + } + + func testEndWithPositives() { + expect([1, 2, 3]).to(endWith(3)) + expect([1, 2, 3]).toNot(endWith(2)) + expect([]).toNot(endWith(1)) + expect(["a", "b", "a"]).to(endWith("a")) + + expect("foobar").to(endWith("bar")) + expect("foobar").toNot(endWith("oo")) + expect("foobarfoo").to(endWith("foo")) + + expect(NSString(string: "foobar").description).to(endWith("bar")) + expect(NSString(string: "foobar").description).toNot(endWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(endWith("b")) + expect(NSArray(array: ["a", "b"])).toNot(endWith("a")) + expect(NSArray(array: [])).toNot(endWith("a")) + expect(NSArray(array: ["a", "b", "a"])).to(endWith("a")) +#endif + } + + func testEndWithNegatives() { + failsWithErrorMessageForNil("expected to end with <2>, got ") { + expect(nil as [Int]?).to(endWith(2)) + } + failsWithErrorMessageForNil("expected to not end with <2>, got ") { + expect(nil as [Int]?).toNot(endWith(2)) + } + + failsWithErrorMessage("expected to end with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(endWith(2)) + } + failsWithErrorMessage("expected to not end with <3>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(endWith(3)) + } + failsWithErrorMessage("expected to end with , got ") { + expect("batman").to(endWith("atm")) + } + failsWithErrorMessage("expected to not end with , got ") { + expect("batman").toNot(endWith("man")) + } + } + +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..85be751 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift @@ -0,0 +1,276 @@ +import Foundation +import XCTest +import Nimble + +final class EqualTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EqualTest) -> () throws -> Void)] { + return [ + ("testEquality", testEquality), + ("testArrayEquality", testArrayEquality), + ("testSetEquality", testSetEquality), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ("testDictionaryEquality", testDictionaryEquality), + ("testDataEquality", testDataEquality), + ("testNSObjectEquality", testNSObjectEquality), + ("testOperatorEquality", testOperatorEquality), + ("testOperatorEqualityWithArrays", testOperatorEqualityWithArrays), + ("testOperatorEqualityWithDictionaries", testOperatorEqualityWithDictionaries), + ("testOptionalEquality", testOptionalEquality), + ("testArrayOfOptionalsEquality", testArrayOfOptionalsEquality), + ("testDictionariesWithDifferentSequences", testDictionariesWithDifferentSequences), + ] + } + + func testEquality() { + expect(1 as CInt).to(equal(1 as CInt)) + expect(1 as CInt).to(equal(1)) + expect(1).to(equal(1)) + expect("hello").to(equal("hello")) + expect("hello").toNot(equal("world")) + + expect { + 1 + }.to(equal(1)) + + failsWithErrorMessage("expected to equal , got ") { + expect("hello").to(equal("world")) + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello").toNot(equal("hello")) + } + } + + func testArrayEquality() { + expect([1, 2, 3]).to(equal([1, 2, 3])) + expect([1, 2, 3]).toNot(equal([1, 2])) + expect([1, 2, 3]).toNot(equal([1, 2, 4])) + + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + expect(array1).to(equal(array2)) + expect(array1).to(equal([1, 2, 3])) + expect(array1).toNot(equal([1, 2] as [Int])) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: [1, 2, 3])).to(equal(NSArray(array: [1, 2, 3]))) +#endif + + failsWithErrorMessage("expected to equal <[1, 2]>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(equal([1, 2])) + } + } + + func testSetEquality() { + expect(Set([1, 2])).to(equal(Set([1, 2]))) + expect(Set()).to(equal(Set())) + expect(Set()) == Set() + expect(Set([1, 2])) != Set() + + failsWithErrorMessageForNil("expected to equal <[1, 2]>, got ") { + expect(nil as Set?).to(equal(Set([1, 2]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3]>, missing <[1]>") { + expect(Set([2, 3])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[1, 2, 3, 4]>, extra <[4]>") { + expect(Set([1, 2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])) == Set([1, 2, 3]) + } + + failsWithErrorMessage("expected to not equal <[1, 2, 3]>, got <[1, 2, 3]>") { + expect(Set([1, 2, 3])) != Set([1, 2, 3]) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as String?).to(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect("foo").toNot(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect(nil as String?).toNot(equal("bar")) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int]?).to(equal(nil as [Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1]>, got ") { + expect(nil as [Int]?).toNot(equal([1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1]>") { + expect([1]).toNot(equal(nil as [Int]?)) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int: Int]?).to(equal(nil as [Int: Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1: 1]>, got ") { + expect(nil as [Int: Int]?).toNot(equal([1: 1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1: 1]>") { + expect([1: 1]).toNot(equal(nil as [Int: Int]?)) + } + + failsWithErrorMessageForNil("expected to not equal , got <1>") { + expect(1).toNot(equal(nil)) + } + } + + func testDictionaryEquality() { + expect(["foo": "bar"]).to(equal(["foo": "bar"])) + expect(["foo": "bar"]).toNot(equal(["foo": "baz"])) + + let actual = ["foo": "bar"] + let expected = ["foo": "bar"] + let unexpected = ["foo": "baz"] + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString)).to(equal(["foo": "bar"])) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString) as? [String: String]).to(equal(expected)) +#endif + } + + func testDataEquality() { + let actual = "foobar".data(using: .utf8) + let expected = "foobar".data(using: .utf8) + let unexpected = "foobarfoo".data(using: .utf8) + + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11) + let expectedErrorMessage = "expected to equal >, got >" + #else + let expectedErrorMessage = "expected to equal >," + + " got >" + #endif + + failsWithErrorMessage(expectedErrorMessage) { + expect(actual).to(equal(unexpected)) + } + } + + func testNSObjectEquality() { + expect(NSNumber(value: 1)).to(equal(NSNumber(value: 1))) + expect(NSNumber(value: 1)) == NSNumber(value: 1) + expect(NSNumber(value: 1)) != NSNumber(value: 2) + expect { NSNumber(value: 1) }.to(equal(1)) + } + + func testOperatorEquality() { + expect("foo") == "foo" + expect("foo") != "bar" + + failsWithErrorMessage("expected to equal , got ") { + expect("hello") == "world" + return + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello") != "hello" + return + } + } + + func testOperatorEqualityWithArrays() { + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + let array3: [Int] = [1, 2] + expect(array1) == array2 + expect(array1) != array3 + } + + func testOperatorEqualityWithDictionaries() { + let dict1 = ["foo": "bar"] + let dict2 = ["foo": "bar"] + let dict3 = ["foo": "baz"] + expect(dict1) == dict2 + expect(dict1) != dict3 + } + + func testOptionalEquality() { + expect(1 as CInt?).to(equal(1)) + expect(1 as CInt?).to(equal(1 as CInt?)) + } + + func testArrayOfOptionalsEquality() { + let array1: [Int?] = [1, nil, 3] + let array2: [Int?] = [nil, 2, 3] + let array3: [Int?] = [1, nil, 3] + + expect(array1).toNot(equal(array2)) + expect(array1).to(equal(array3)) + expect(array2).toNot(equal(array3)) + + let allNils1: [String?] = [nil, nil, nil, nil] + let allNils2: [String?] = [nil, nil, nil, nil] + let notReallyAllNils: [String?] = [nil, nil, nil, "turtles"] + + expect(allNils1).to(equal(allNils2)) + expect(allNils1).toNot(equal(notReallyAllNils)) + + let noNils1: [Int?] = [1, 2, 3, 4, 5] + let noNils2: [Int?] = [1, 3, 5, 7, 9] + + expect(noNils1).toNot(equal(noNils2)) + + failsWithErrorMessage("expected to equal <[Optional(1), nil]>, got <[nil, Optional(2)]>") { + let arrayOfOptionalInts: [Int?] = [nil, 2] + let anotherArrayOfOptionalInts: [Int?] = [1, nil] + expect(arrayOfOptionalInts).to(equal(anotherArrayOfOptionalInts)) + return + } + } + + func testDictionariesWithDifferentSequences() { + // see: https://github.com/Quick/Nimble/issues/61 + // these dictionaries generate different orderings of sequences. + let result = ["how": 1, "think": 1, "didnt": 2, "because": 1, + "interesting": 1, "always": 1, "right": 1, "such": 1, + "to": 3, "say": 1, "cool": 1, "you": 1, + "weather": 3, "be": 1, "went": 1, "was": 2, + "sometimes": 1, "and": 3, "mind": 1, "rain": 1, + "whole": 1, "everything": 1, "weather.": 1, "down": 1, + "kind": 1, "mood.": 1, "it": 2, "everyday": 1, "might": 1, + "more": 1, "have": 2, "person": 1, "could": 1, "tenth": 2, + "night": 1, "write": 1, "Youd": 1, "affects": 1, "of": 3, + "Who": 1, "us": 1, "an": 1, "I": 4, "my": 1, "much": 2, + "wrong.": 1, "peacefully.": 1, "amazing": 3, "would": 4, + "just": 1, "grade.": 1, "Its": 2, "The": 2, "had": 1, "that": 1, + "the": 5, "best": 1, "but": 1, "essay": 1, "for": 1, "summer": 2, + "your": 1, "grade": 1, "vary": 1, "pretty": 1, "at": 1, "rain.": 1, + "about": 1, "allow": 1, "thought": 1, "in": 1, "sleep": 1, "a": 1, + "hot": 1, "really": 1, "beach": 1, "life.": 1, "we": 1, "although": 1, ] + + let storyCount = ["The": 2, "summer": 2, "of": 3, "tenth": 2, "grade": 1, + "was": 2, "the": 5, "best": 1, "my": 1, "life.": 1, "I": 4, + "went": 1, "to": 3, "beach": 1, "everyday": 1, "and": 3, + "we": 1, "had": 1, "amazing": 3, "weather.": 1, "weather": 3, + "didnt": 2, "really": 1, "vary": 1, "much": 2, "always": 1, + "pretty": 1, "hot": 1, "although": 1, "sometimes": 1, "at": 1, + "night": 1, "it": 2, "would": 4, "rain.": 1, "mind": 1, "rain": 1, + "because": 1, "cool": 1, "everything": 1, "down": 1, "allow": 1, + "us": 1, "sleep": 1, "peacefully.": 1, "Its": 2, "how": 1, + "affects": 1, "your": 1, "mood.": 1, "Who": 1, "have": 2, + "thought": 1, "that": 1, "could": 1, "write": 1, "a": 1, + "whole": 1, "essay": 1, "just": 1, "about": 1, "in": 1, + "grade.": 1, "kind": 1, "right": 1, "Youd": 1, "think": 1, + "for": 1, "such": 1, "an": 1, "interesting": 1, "person": 1, + "might": 1, "more": 1, "say": 1, "but": 1, "you": 1, "be": 1, "wrong.": 1, ] + + expect(result).to(equal(storyCount)) + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble + +final class HaveCountTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (HaveCountTest) -> () throws -> Void)] { + return [ + ("testHaveCountForArray", testHaveCountForArray), + ("testHaveCountForDictionary", testHaveCountForDictionary), + ("testHaveCountForSet", testHaveCountForSet), + ] + } + + func testHaveCountForArray() { + expect([1, 2, 3]).to(haveCount(3)) + expect([1, 2, 3]).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Array with count 1, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Array with count 3, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).notTo(haveCount(3)) + } + } + + func testHaveCountForDictionary() { + let dictionary = ["1": 1, "2": 2, "3": 3] + expect(dictionary).to(haveCount(3)) + expect(dictionary).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Dictionary with count 1, got 3\nActual Value: \(stringify(dictionary))") { + expect(dictionary).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Dictionary with count 3, got 3" + + "\nActual Value: \(stringify(dictionary))") { + expect(dictionary).notTo(haveCount(3)) + } + } + + func testHaveCountForSet() { + let set = Set([1, 2, 3]) + expect(set).to(haveCount(3)) + expect(set).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Set with count 1, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Set with count 3, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).notTo(haveCount(3)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..946e4cd --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift @@ -0,0 +1,84 @@ +import Foundation +import XCTest +import Nimble + +final class MatchErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchErrorTest) -> () throws -> Void)] { + return [ + ("testMatchErrorPositive", testMatchErrorPositive), + ("testMatchErrorNegative", testMatchErrorNegative), + ("testMatchNSErrorPositive", testMatchNSErrorPositive), + ("testMatchNSErrorNegative", testMatchNSErrorNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ] + } + + func testMatchErrorPositive() { + expect(NimbleError.laugh).to(matchError(NimbleError.laugh)) + expect(NimbleError.laugh).to(matchError(NimbleError.self)) + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 1))) + + expect(NimbleError.laugh as Error).to(matchError(NimbleError.laugh)) + } + + func testMatchErrorNegative() { + expect(NimbleError.laugh).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh as Error).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh).toNot(matchError(EquatableError.self)) + expect(EquatableError.parameterized(x: 1)).toNot(matchError(EquatableError.parameterized(x: 2))) + } + + func testMatchNSErrorPositive() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 0, userInfo: nil) + + expect(error1).to(matchError(error2)) + } + + func testMatchNSErrorNegative() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + + expect(error1).toNot(matchError(error2)) + } + + func testMatchPositiveMessage() { + failsWithErrorMessage("expected to match error , got ") { + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 2))) + } + failsWithErrorMessage("expected to match error , got ") { + expect(NimbleError.laugh).to(matchError(NimbleError.cry)) + } + failsWithErrorMessage("expected to match error , got ") { + expect(CustomDebugStringConvertibleError.a).to(matchError(CustomDebugStringConvertibleError.b)) + } + + failsWithErrorMessage("expected to match error , got ") { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + expect(error1).to(matchError(error2)) + } + } + + func testMatchNegativeMessage() { + failsWithErrorMessage("expected to not match error , got ") { + expect(NimbleError.laugh).toNot(matchError(NimbleError.laugh)) + } + + failsWithErrorMessage("expected to match error from type , got ") { + expect(NimbleError.laugh).to(matchError(EquatableError.self)) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to match error , got no error") { + expect(nil as Error?).to(matchError(NimbleError.laugh)) + } + + failsWithErrorMessageForNil("expected to not match error , got no error") { + expect(nil as Error?).toNot(matchError(NimbleError.laugh)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift @@ -0,0 +1,46 @@ +import XCTest +import Nimble + +final class MatchTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchTest) -> () throws -> Void)] { + return [ + ("testMatchPositive", testMatchPositive), + ("testMatchNegative", testMatchNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testMatchNils", testMatchNils), + ] + } + + func testMatchPositive() { + expect("11:14").to(match("\\d{2}:\\d{2}")) + } + + func testMatchNegative() { + expect("hello").toNot(match("\\d{2}:\\d{2}")) + } + + func testMatchPositiveMessage() { + let message = "expected to match <\\d{2}:\\d{2}>, got " + failsWithErrorMessage(message) { + expect("hello").to(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNegativeMessage() { + let message = "expected to not match <\\d{2}:\\d{2}>, got <11:14>" + failsWithErrorMessage(message) { + expect("11:14").toNot(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNils() { + failsWithErrorMessageForNil("expected to match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).to(match("\\d{2}:\\d{2}")) + } + + failsWithErrorMessageForNil("expected to not match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).toNot(match("\\d{2}:\\d{2}")) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..ac7f9ec --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift @@ -0,0 +1,91 @@ +import XCTest +import Nimble +import Foundation + +final class PostNotificationTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PostNotificationTest) -> () throws -> Void)] { + return [ + ("testPassesWhenNoNotificationsArePosted", testPassesWhenNoNotificationsArePosted), + ("testPassesWhenExpectedNotificationIsPosted", testPassesWhenExpectedNotificationIsPosted), + ("testPassesWhenAllExpectedNotificationsArePosted", testPassesWhenAllExpectedNotificationsArePosted), + ("testFailsWhenNoNotificationsArePosted", testFailsWhenNoNotificationsArePosted), + ("testFailsWhenNotificationWithWrongNameIsPosted", testFailsWhenNotificationWithWrongNameIsPosted), + ("testFailsWhenNotificationWithWrongObjectIsPosted", testFailsWhenNotificationWithWrongObjectIsPosted), + ("testPassesWhenExpectedNotificationEventuallyIsPosted", testPassesWhenExpectedNotificationEventuallyIsPosted), + ] + } + + let notificationCenter = NotificationCenter() + + func testPassesWhenNoNotificationsArePosted() { + expect { + // no notifications here! + return nil + }.to(postNotifications(beEmpty(), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenExpectedNotificationIsPosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + self.notificationCenter.post(testNotification) + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenAllExpectedNotificationsArePosted() { + let foo = NSNumber(value: 1) + let bar = NSNumber(value: 2) + let n1 = Notification(name: Notification.Name("Foo"), object: foo) + let n2 = Notification(name: Notification.Name("Bar"), object: bar) + expect { + self.notificationCenter.post(n1) + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1, n2]), fromNotificationCenter: notificationCenter)) + } + + func testFailsWhenNoNotificationsArePosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + failsWithErrorMessage("expected to equal <[\(testNotification)]>, got no notifications") { + expect { + // no notifications here! + return nil + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongNameIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: Notification.Name(n1.name.rawValue + "a"), object: nil) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongObjectIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: n1.name, object: NSObject()) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testPassesWhenExpectedNotificationEventuallyIsPosted() { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + deferToMainQueue { + self.notificationCenter.post(testNotification) + } + return nil + }.toEventually(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + #else + print("\(#function) is missing because toEventually is not implement on this platform") + #endif + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..f62f633 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class RaisesExceptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (RaisesExceptionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testNegativeMatchesDoNotCallClosureWithoutException", testNegativeMatchesDoNotCallClosureWithoutException), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + var anException = NSException(name: NSExceptionName("laugh"), reason: "Lulz", userInfo: ["key": "value"]) + + func testPositiveMatches() { + expect { self.anException.raise() }.to(raiseException()) + expect { self.anException.raise() }.to(raiseException(named: "laugh")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + + func testPositiveMatchesWithClosures() { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName("laugh"))) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("df")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + failsWithErrorMessage("expected to raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "foo")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "bar")) + } + + failsWithErrorMessage( + "expected to raise exception with name with reason with userInfo <{k = v;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["k": "v"])) + } + + failsWithErrorMessage("expected to raise any exception, got no exception") { + expect { self.anException }.to(raiseException()) + } + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + failsWithErrorMessage("expected to raise exception with name with reason , got no exception") { + expect { self.anException }.to(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "bar", reason: "Lulz")) + } + failsWithErrorMessage("expected to not raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh")) + } + failsWithErrorMessage("expected to not raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to not raise exception with name with reason with userInfo <{key = value;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutException() { + failsWithErrorMessage("expected to raise exception that satisfies block, got no exception") { + expect { self.anException }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName(rawValue: "foo"))) + }) + } + + failsWithErrorMessage("expected to raise exception with name that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "ha") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason with userInfo <{}> that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + } + + func testNegativeMatchesWithClosure() { + failsWithErrorMessage("expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + let innerFailureMessage = "expected to begin with , got " + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "wrong") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + } +} +#endif diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift new file mode 100644 index 0000000..42ed892 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift @@ -0,0 +1,57 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAllOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAllOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAllOf", testSatisfyAllOf), + ("testOperatorAnd", testOperatorAnd), + ] + } + + func testSatisfyAllOf() { + expect(2).to(satisfyAllOf(equal(2), beLessThan(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAllOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAllOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAllOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").to(satisfyAllOf(contain("e"), beginWith("tur"))) + expect(82.0).to(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(82.00001))) + expect(false).toNot(satisfyAllOf(beTrue(), beFalse())) + expect(true).toNot(satisfyAllOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2") { + expect(2).to(satisfyAllOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match all of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, and {equal <[5, 6, 7]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAllOf(allPass("be less than 4", {$0 < 4}), equal([5, 6, 7]))) + } + failsWithErrorMessage( + "expected to not match all of: {be false}, got false") { + expect(false).toNot(satisfyAllOf(beFalse())) + } + failsWithErrorMessage( + "expected to not match all of: {be greater than <10.5>}, and {be less than <100.75>}, and {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorAnd() { + expect(2).to(equal(2) && beLessThan(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).to(beLessThan(3) && beGreaterThan(1)) +#else + expect(2 as NSNumber).to(beLessThan(3 as NSNumber) && beGreaterThan(1 as NSNumber)) +#endif + expect("turtle").to(contain("t") && endWith("tle")) + expect(82.0).to(beGreaterThan(10.5) && beLessThan(100.75)) + expect(false).to(beFalsy() && beFalse()) + expect(false).toNot(beTrue() && beFalse()) + expect(true).toNot(beTruthy() && beFalsy()) + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAnyOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAnyOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAnyOf", testSatisfyAnyOf), + ("testOperatorOr", testOperatorOr), + ] + } + + func testSatisfyAnyOf() { + expect(2).to(satisfyAnyOf(equal(2), equal(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAnyOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAnyOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAnyOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").toNot(satisfyAnyOf(contain("a"), endWith("magic"))) + expect(82.0).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + expect(false).to(satisfyAnyOf(beTrue(), beFalse())) + expect(true).to(satisfyAnyOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2") { + expect(2).to(satisfyAnyOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match one of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, or {equal <[1, 2, 3, 4]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAnyOf(allPass("be less than 4", {$0 < 4}), equal([1, 2, 3, 4]))) + } + failsWithErrorMessage( + "expected to match one of: {be true}, got false") { + expect(false).to(satisfyAnyOf(beTrue())) + } + failsWithErrorMessage( + "expected to not match one of: {be less than <10.5>}, or {be greater than <100.75>}, or {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorOr() { + expect(2).to(equal(2) || equal(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(equal(3) || equal("turtles")) +#else + expect(2 as NSNumber).toNot(equal(3 as NSNumber) || equal("turtles" as NSString)) +#endif + expect("turtle").toNot(contain("a") || endWith("magic")) + expect(82.0).toNot(beLessThan(10.5) || beGreaterThan(100.75)) + expect(false).to(beTrue() || beFalse()) + expect(true).to(beTruthy() || beFalsy()) + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..4babde0 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,68 @@ +import Foundation +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +private let error: Error = NSError(domain: "test", code: 0, userInfo: nil) + +final class ThrowAssertionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowAssertionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testErrorThrown", testErrorThrown), + ("testPostAssertionCodeNotRun", testPostAssertionCodeNotRun), + ("testNegativeMatch", testNegativeMatch), + ("testPositiveMessage", testPositiveMessage), + ("testNegativeMessage", testNegativeMessage), + ] + } + + func testPositiveMatch() { + expect { () -> Void in fatalError() }.to(throwAssertion()) + } + + func testErrorThrown() { + expect { throw error }.toNot(throwAssertion()) + } + + func testPostAssertionCodeNotRun() { + var reachedPoint1 = false + var reachedPoint2 = false + + expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true + }.to(throwAssertion()) + + expect(reachedPoint1) == true + expect(reachedPoint2) == false + } + + func testNegativeMatch() { + var reachedPoint1 = false + + expect { reachedPoint1 = true }.toNot(throwAssertion()) + + expect(reachedPoint1) == true + } + + func testPositiveMessage() { + failsWithErrorMessage("expected to throw an assertion") { + expect { () -> Void? in return }.to(throwAssertion()) + } + + failsWithErrorMessage("expected to throw an assertion; threw error instead <\(error)>") { + expect { throw error }.to(throwAssertion()) + } + } + + func testNegativeMessage() { + failsWithErrorMessage("expected to not throw an assertion") { + expect { () -> Void in fatalError() }.toNot(throwAssertion()) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..f862992 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift @@ -0,0 +1,164 @@ +import XCTest +import Nimble + +enum NimbleError: Error { + case laugh + case cry +} + +enum EquatableError: Error { + case parameterized(x: Int) +} + +extension EquatableError: CustomDebugStringConvertible { + var debugDescription: String { + switch self { + case .parameterized(let x): + return "parameterized(x: \(x))" + } + } +} + +extension EquatableError: Equatable { +} + +func == (lhs: EquatableError, rhs: EquatableError) -> Bool { + switch (lhs, rhs) { + case (.parameterized(let l), .parameterized(let r)): + return l == r + } +} + +enum CustomDebugStringConvertibleError: Error { + case a + case b +} + +extension CustomDebugStringConvertibleError: CustomDebugStringConvertible { + var debugDescription: String { + return "code=\(_code)" + } +} + +final class ThrowErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowErrorTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testPositiveNegatedMatches", testPositiveNegatedMatches), + ("testNegativeNegatedMatches", testNegativeNegatedMatches), + ("testNegativeMatchesDoNotCallClosureWithoutError", testNegativeMatchesDoNotCallClosureWithoutError), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + func testPositiveMatches() { + expect { throw NimbleError.laugh }.to(throwError()) + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh)) + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self)) + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 1))) + expect { throw EquatableError.parameterized(x: 1) }.toNot(throwError(EquatableError.parameterized(x: 2))) + } + + func testPositiveMatchesWithClosures() { + // Generic typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { error in + guard case EquatableError.parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Explicit typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { (error: EquatableError) in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over errorType argument + expect { throw EquatableError.parameterized(x: 42) }.to(throwError(errorType: EquatableError.self) { error in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).to(beginWith("Nim")) + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Different case + failsWithErrorMessage("expected to throw error , got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry)) + } + // Different case with closure + failsWithErrorMessage("expected to throw error that satisfies block, got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry) { _ in return }) + } + // Different case, implementing CustomDebugStringConvertible + failsWithErrorMessage("expected to throw error , got ") { + expect { throw CustomDebugStringConvertibleError.a }.to(throwError(CustomDebugStringConvertibleError.b)) + } + } + + func testPositiveNegatedMatches() { + // No error at all + expect { return }.toNot(throwError()) + // Different case + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.cry)) + } + + func testNegativeNegatedMatches() { + // No error at all + failsWithErrorMessage("expected to not throw any error, got ") { + expect { throw NimbleError.laugh }.toNot(throwError()) + } + // Different error + failsWithErrorMessage("expected to not throw error , got ") { + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.laugh)) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutError() { + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError { _ in + fail() + }) + } + + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError(NimbleError.laugh) { _ in + fail() + }) + } + } + + func testNegativeMatchesWithClosure() { + let moduleName = "NimbleTests" + let innerFailureMessage = "expected to equal , got <\(moduleName).NimbleError>" + let closure = { (error: Error) in + expect(error._domain).to(equal("foo")) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error from type that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self, closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh, closure: closure)) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift new file mode 100644 index 0000000..dde999a --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift @@ -0,0 +1,36 @@ +import XCTest +import Nimble + +final class ToSucceedTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ToSucceedTest) -> () throws -> Void)] { + return [ + ("testToSucceed", testToSucceed), + ] + } + + func testToSucceed() { + expect({ + return .succeeded + }).to(succeed()) + + expect({ + return .failed(reason: "") + }).toNot(succeed()) + + failsWithErrorMessageForNil("expected a closure, got ") { + expect(nil as (() -> ToSucceedResult)?).to(succeed()) + } + + failsWithErrorMessage("expected to succeed, got because ") { + expect({ + .failed(reason: "something went wrong") + }).to(succeed()) + } + + failsWithErrorMessage("expected to not succeed, got ") { + expect({ + return .succeeded + }).toNot(succeed()) + } + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTest.swift new file mode 100644 index 0000000..f1ba572 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTest.swift @@ -0,0 +1,161 @@ +import Foundation +import XCTest +import Nimble + +final class SynchronousTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SynchronousTest) -> () throws -> Void)] { + return [ + ("testFailAlwaysFails", testFailAlwaysFails), + ("testUnexpectedErrorsThrownFails", testUnexpectedErrorsThrownFails), + ("testToMatchesIfMatcherReturnsTrue", testToMatchesIfMatcherReturnsTrue), + ("testToProvidesActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToMatchAgainstLazyProperties", testToMatchAgainstLazyProperties), + ("testToNotMatchesIfMatcherReturnsTrue", testToNotMatchesIfMatcherReturnsTrue), + ("testToNotProvidesActualValueExpression", testToNotProvidesActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpression", testToNotProvidesAMemoizedActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToNegativeMatches", testToNegativeMatches), + ("testToNotNegativeMatches", testToNotNegativeMatches), + ("testNotToMatchesLikeToNot", testNotToMatchesLikeToNot), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testFailAlwaysFails() { + failsWithErrorMessage("My error message") { + fail("My error message") + } + failsWithErrorMessage("fail() always fails") { + fail() + } + } + + func testUnexpectedErrorsThrownFails() { + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.to(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toNot(equal(1)) + } + } + + func testToMatchesIfMatcherReturnsTrue() { + expect(1).to(MatcherFunc { _, _ in true }) + expect {1}.to(MatcherFunc { _, _ in true }) + + expect(1).to(MatcherFunc { _, _ in true }.predicate) + expect {1}.to(MatcherFunc { _, _ in true }.predicate) + + expect(1).to(Predicate.simple("match") { _ in .matches }) + expect {1}.to(Predicate.simple("match") { _ in .matches }) + } + + func testToProvidesActualValueExpression() { + var value: Int? + expect(1).to(MatcherFunc { expr, _ in value = try expr.evaluate(); return true }) + expect(value).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToMatchAgainstLazyProperties() { + expect(ObjectWithLazyProperty().value).to(equal("hello")) + expect(ObjectWithLazyProperty().value).toNot(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).to(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).toNot(equal("hello")) + } + + // repeated tests from to() for toNot() + func testToNotMatchesIfMatcherReturnsTrue() { + expect(1).toNot(MatcherFunc { _, _ in false }) + expect {1}.toNot(MatcherFunc { _, _ in false }) + + expect(1).toNot(MatcherFunc { _, _ in false }.predicate) + expect {1}.toNot(MatcherFunc { _, _ in false }.predicate) + + expect(1).toNot(Predicate.simple("match") { _ in .doesNotMatch }) + expect {1}.toNot(Predicate.simple("match") { _ in .doesNotMatch }) + } + + func testToNotProvidesActualValueExpression() { + var value: Int? + expect(1).toNot(MatcherFunc { expr, _ in value = try expr.evaluate(); return false }) + expect(value).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNegativeMatches() { + failsWithErrorMessage("expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }) + } + failsWithErrorMessage("expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }.predicate) + } + failsWithErrorMessage("expected to match, got <1>") { + expect(1).to(Predicate.simple("match") { _ in .doesNotMatch }) + } + } + + func testToNotNegativeMatches() { + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }) + } + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }.predicate) + } + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(Predicate.simple("match") { _ in .matches }) + } + } + + func testNotToMatchesLikeToNot() { + expect(1).notTo(MatcherFunc { _, _ in false }) + expect(1).notTo(MatcherFunc { _, _ in false }.predicate) + expect(1).notTo(Predicate.simple("match") { _ in .doesNotMatch }) + } +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift @@ -0,0 +1,64 @@ +import XCTest +import Nimble + +final class UserDescriptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (UserDescriptionTest) -> () throws -> Void)] { + return [ + ("testToMatcher_CustomFailureMessage", testToMatcher_CustomFailureMessage), + ("testNotToMatcher_CustomFailureMessage", testNotToMatcher_CustomFailureMessage), + ("testToNotMatcher_CustomFailureMessage", testToNotMatcher_CustomFailureMessage), + ("testToEventuallyMatch_CustomFailureMessage", testToEventuallyMatch_CustomFailureMessage), + ("testToEventuallyNotMatch_CustomFailureMessage", testToEventuallyNotMatch_CustomFailureMessage), + ("testToNotEventuallyMatch_CustomFailureMessage", testToNotEventuallyMatch_CustomFailureMessage), + ] + } + + func testToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }, description: "These aren't equal!") + } + } + + func testNotToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).notTo(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToNotMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't eventually equal!\n" + + "expected to eventually equal <1>, got <0>") { + expect { 0 }.toEventually(equal(1), description: "These aren't eventually equal!") + } + } + + func testToEventuallyNotMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + + func testToNotEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + +} diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h @@ -0,0 +1,15 @@ +@import Nimble; +#import "NimbleTests-Swift.h" + +// Use this when you want to verify the failure message for when an expectation fails +#define expectFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessage:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + +#define expectFailureMessages(MSGS, BLOCK) \ +[NimbleHelper expectFailureMessages:(MSGS) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + + +// Use this when you want to verify the failure message with the nil message postfixed +// to it: " (use beNil() to match nils)" +#define expectNilFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessageForNil:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..4bdc021 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m @@ -0,0 +1,38 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAllPassTest : XCTestCase + +@end + +@implementation ObjCAllPassTest + +- (void)testPositiveMatches { + expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); + expect(@[@1, @2, @3,@4]).toNot(allPass(beGreaterThan(@5))); + + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).to(allPass(beLessThan(@5))); + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).toNot(allPass(beGreaterThan(@5))); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to all be less than <3>, but failed first at element" + " <3> in <[1, 2, 3, 4]>", ^{ + expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@3))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect(@[@1, @2, @3, @4]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect([NSSet setWithArray:@[@1, @2, @3, @4]]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).to(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).toNot(allPass(beLessThan(@5))); + }); +} +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m @@ -0,0 +1,55 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAsyncTest : XCTestCase + +@end + +@implementation ObjCAsyncTest + +- (void)testAsync { + __block id obj = @1; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = nil; + }); + expect(obj).toEventually(beNil()); +} + + +- (void)testAsyncWithCustomTimeout { + __block id obj = nil; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = @1; + }); + expect(obj).withTimeout(5).toEventuallyNot(beNil()); +} + +- (void)testAsyncCallback { + waitUntil(^(void (^done)(void)){ + done(); + }); + + expectFailureMessage(@"Waited more than 1.0 second", ^{ + waitUntil(^(void (^done)(void)){ /* ... */ }); + }); + + expectFailureMessage(@"Waited more than 0.01 seconds", ^{ + waitUntilTimeout(0.01, ^(void (^done)(void)){ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [NSThread sleepForTimeInterval:0.1]; + done(); + }); + }); + }); + + expectFailureMessage(@"expected to equal , got ", ^{ + waitUntil(^(void (^done)(void)){ + [NSThread sleepForTimeInterval:0.1]; + expect(@"hello").to(equal(@"goodbye")); + done(); + }); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeAnInstanceOfTest : XCTestCase +@end + +@implementation ObjCBeAnInstanceOfTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beAnInstanceOf([NSNull class])); + expect(@1).toNot(beAnInstanceOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be an instance of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAnInstanceOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAnInstanceOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be an instance of NSNull, got ", ^{ + expect(nil).to(beAnInstanceOf([NSNull class])); + }); + + expectNilFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect(nil).toNot(beAnInstanceOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeCloseToTest : XCTestCase + +@end + +@implementation ObjCBeCloseToTest + +- (void)testPositiveMatches { + expect(@1.2).to(beCloseTo(@1.2001)); + expect(@1.2).to(beCloseTo(@2).within(10)); + expect(@2).toNot(beCloseTo(@1)); + expect(@1.00001).toNot(beCloseTo(@1).within(0.00000001)); + + expect(1.2).to(beCloseTo(1.2001)); + expect(1.2).to(beCloseTo(2).within(10)); + expect(2).toNot(beCloseTo(1)); + expect(1.00001).toNot(beCloseTo(1).within(0.00000001)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(@1).to(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(@(0.0001)).toNot(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(1).to(beCloseTo(0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(0.0001).toNot(beCloseTo(0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be close to <0> (within 0.001), got ", ^{ + expect(nil).to(beCloseTo(@0)); + }); + expectNilFailureMessage(@"expected to not be close to <0> (within 0.001), got ", ^{ + expect(nil).toNot(beCloseTo(@0)); + }); +} + + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..5e803cb --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m @@ -0,0 +1,89 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeEmptyTest : XCTestCase +@end + +@implementation ObjCBeEmptyTest + +- (void)testPositiveMatches { + expect(@[]).to(beEmpty()); + expect(@"").to(beEmpty()); + expect(@{}).to(beEmpty()); + expect([NSSet set]).to(beEmpty()); + expect([NSIndexSet indexSet]).to(beEmpty()); + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]).to(beEmpty()); + + expect(@[@1, @2]).toNot(beEmpty()); + expect(@"a").toNot(beEmpty()); + expect(@{@"key": @"value"}).toNot(beEmpty()); + expect([NSSet setWithObject:@1]).toNot(beEmpty()); + expect([NSIndexSet indexSetWithIndex:1]).toNot(beEmpty()); + + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + expect(table).toNot(beEmpty()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be empty, got ", ^{ + expect(@"foo").to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect(@[@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{key = value;}>", ^{ + expect(@{@"key": @"value"}).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{(1)}>", ^{ + expect([NSSet setWithObject:@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect([NSIndexSet indexSetWithIndex:1]).to(beEmpty()); + }); + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + NSString *tableString = [[table description] stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be empty, got <%@>", tableString]), ^{ + expect(table).to(beEmpty()); + }); + + expectFailureMessage(@"expected to not be empty, got <>", ^{ + expect(@"").toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect(@[]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{}>", ^{ + expect(@{}).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{()}>", ^{ + expect([NSSet set]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect([NSIndexSet indexSet]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got ", ^{ + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]).toNot(beEmpty()); + }); +} + +- (void)testItDoesNotMatchNil { + expectNilFailureMessage(@"expected to be empty, got ", ^{ + expect(nil).to(beEmpty()); + }); + expectNilFailureMessage(@"expected to not be empty, got ", ^{ + expect(nil).toNot(beEmpty()); + }); +} + +- (void)testItReportsTypesItMatchesAgainst { + expectFailureMessage(@"expected to be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).to(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).toNot(beEmpty()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m @@ -0,0 +1,46 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalseTest : XCTestCase + +@end + +@implementation ObjCBeFalseTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalse()); + expect(@YES).toNot(beFalse()); + + expect(false).to(beFalse()); + expect(true).toNot(beFalse()); + + expect(NO).to(beFalse()); + expect(YES).toNot(beFalse()); + + expect(10).toNot(beFalse()); +} + +- (void)testNegativeMatches { + expectNilFailureMessage(@"expected to be false, got ", ^{ + expect(nil).to(beFalse()); + }); + expectNilFailureMessage(@"expected to not be false, got ", ^{ + expect(nil).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(true).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(false).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(YES).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(NO).toNot(beFalse()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m @@ -0,0 +1,58 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalsyTest : XCTestCase + +@end + +@implementation ObjCBeFalsyTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalsy()); + expect(@YES).toNot(beFalsy()); + expect(nil).to(beFalsy()); + + expect(true).toNot(beFalsy()); + expect(false).to(beFalsy()); + + expect(YES).toNot(beFalsy()); + expect(NO).to(beFalsy()); + + expect(10).toNot(beFalsy()); + expect(0).to(beFalsy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to not be falsy, got ", ^{ + expect(nil).toNot(beFalsy()); + }); + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(@1).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(@NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(true).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(false).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(YES).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <10>", ^{ + expect(10).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(0).toNot(beFalsy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..28862ba --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m @@ -0,0 +1,44 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThanOrEqualTo(@2)); + expect(@2).toNot(beGreaterThanOrEqualTo(@3)); + expect(2).to(beGreaterThanOrEqualTo(0)); + expect(2).to(beGreaterThanOrEqualTo(2)); + expect(2).toNot(beGreaterThanOrEqualTo(3)); + expect(2.5).to(beGreaterThanOrEqualTo(2)); + expect(2.5).to(beGreaterThanOrEqualTo(2.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThanOrEqualTo(@0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThanOrEqualTo(@(1))); + }); + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(-1).to(beGreaterThanOrEqualTo(0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(2).toNot(beGreaterThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than or equal to <-1>, got ", ^{ + expect(nil).to(beGreaterThanOrEqualTo(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than or equal to <1>, got ", ^{ + expect(nil).toNot(beGreaterThanOrEqualTo(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..5a57d54 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThan(@1)); + expect(@2).toNot(beGreaterThan(@2)); + expect(@2).to(beGreaterThan(0)); + expect(@2).toNot(beGreaterThan(2)); + expect(2.5).to(beGreaterThan(1.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThan(@(0))); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThan(@(1))); + }); + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(-1).to(beGreaterThan(0)); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(2).toNot(beGreaterThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than <-1>, got ", ^{ + expect(nil).to(beGreaterThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than <1>, got ", ^{ + expect(nil).toNot(beGreaterThan(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m @@ -0,0 +1,68 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeIdenticalToTest : XCTestCase + +@end + +@implementation ObjCBeIdenticalToTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beIdenticalTo([NSNull null])); + expect(@2).toNot(beIdenticalTo(@3)); +} + +- (void)testNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(beIdenticalTo(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(beIdenticalTo(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testAliasPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(be([NSNull null])); + expect(@2).toNot(be(@3)); +} + +- (void)testAliasNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(be(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(be(obj)); + }); +} + +- (void)testAliasNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(be(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(be(obj)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeKindOfTest : XCTestCase + +@end + +@implementation ObjCBeKindOfTest + +- (void)testPositiveMatches { + NSMutableArray *array = [NSMutableArray array]; + expect(array).to(beAKindOf([NSArray class])); + expect(@1).toNot(beAKindOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be a kind of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAKindOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAKindOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be a kind of NSNull, got ", ^{ + expect(nil).to(beAKindOf([NSNull class])); + }); + expectNilFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect(nil).toNot(beAKindOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m @@ -0,0 +1,43 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeLessThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThanOrEqualTo(@2)); + expect(@2).toNot(beLessThanOrEqualTo(@1)); + expect(2).to(beLessThanOrEqualTo(2)); + expect(2).toNot(beLessThanOrEqualTo(1)); + expect(2).toNot(beLessThanOrEqualTo(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(@2).to(beLessThanOrEqualTo(@1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(@1).toNot(beLessThanOrEqualTo(@1)); + }); + + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(2).to(beLessThanOrEqualTo(1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(1).toNot(beLessThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than or equal to <1>, got ", ^{ + expect(nil).to(beLessThanOrEqualTo(@1)); + }); + expectNilFailureMessage(@"expected to not be less than or equal to <-1>, got ", ^{ + expect(nil).toNot(beLessThanOrEqualTo(@(-1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..9750641 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanTest : XCTestCase + +@end + +@implementation ObjCBeLessThanTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThan(@3)); + expect(@2).toNot(beLessThan(@2)); + expect(2).to(beLessThan(3)); + expect(2).toNot(beLessThan(2)); + expect(2).toNot(beLessThan(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(@(1)).to(beLessThan(@0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(@0).toNot(beLessThan(@1)); + }); + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(1).to(beLessThan(0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(0).toNot(beLessThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than <-1>, got ", ^{ + expect(nil).to(beLessThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be less than <1>, got ", ^{ + expect(nil).toNot(beLessThan(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m @@ -0,0 +1,24 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeNilTest : XCTestCase + +@end + +@implementation ObjCBeNilTest + +- (void)testPositiveMatches { + expect(nil).to(beNil()); + expect(@NO).toNot(beNil()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be nil, got <1>", ^{ + expect(@1).to(beNil()); + }); + expectFailureMessage(@"expected to not be nil, got ", ^{ + expect(nil).toNot(beNil()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTrueTest : XCTestCase + +@end + +@implementation ObjCBeTrueTest + +- (void)testPositiveMatches { + expect(@YES).to(beTrue()); + expect(@NO).toNot(beTrue()); + expect(nil).toNot(beTrue()); + + expect(true).to(beTrue()); + expect(false).toNot(beTrue()); + + expect(YES).to(beTrue()); + expect(NO).toNot(beTrue()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(@NO).to(beTrue()); + }); + expectFailureMessage(@"expected to be true, got ", ^{ + expect(nil).to(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(false).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(true).toNot(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(NO).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(YES).toNot(beTrue()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m @@ -0,0 +1,55 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTruthyTest : XCTestCase + +@end + +@implementation ObjCBeTruthyTest + +- (void)testPositiveMatches { + expect(@YES).to(beTruthy()); + expect(@NO).toNot(beTruthy()); + expect(nil).toNot(beTruthy()); + + expect(true).to(beTruthy()); + expect(false).toNot(beTruthy()); + + expect(YES).to(beTruthy()); + expect(NO).toNot(beTruthy()); + + expect(10).to(beTruthy()); + expect(0).toNot(beTruthy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be truthy, got ", ^{ + expect(nil).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(@1).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(@NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(false).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(true).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(YES).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <10>", ^{ + expect(10).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(0).to(beTruthy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeginWithTest : XCTestCase + +@end + +@implementation ObjCBeginWithTest + +- (void)testPositiveMatches { + expect(@"hello world!").to(beginWith(@"hello")); + expect(@"hello world!").toNot(beginWith(@"world")); + + NSArray *array = @[@1, @2]; + expect(array).to(beginWith(@1)); + expect(array).toNot(beginWith(@2)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to begin with , got ", ^{ + expect(@"foo").to(beginWith(@"bar")); + }); + expectFailureMessage(@"expected to not begin with , got ", ^{ + expect(@"foo").toNot(beginWith(@"foo")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to begin with <1>, got ", ^{ + expect(nil).to(beginWith(@1)); + }); + expectNilFailureMessage(@"expected to not begin with <1>, got ", ^{ + expect(nil).toNot(beginWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m @@ -0,0 +1,64 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainElementSatisfyingTest : XCTestCase + +@end + +@implementation ObjCContainElementSatisfyingTest + +- (void)testPassingMatches { + NSArray *orderIndifferentArray = @[@1, @2, @3]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + orderIndifferentArray = @[@3, @1, @2]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + NSSet *orderIndifferentSet = [NSSet setWithObjects:@"turtle test", @"turtle assessment", nil]; + expect(orderIndifferentSet).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"turtle assessment"]; + })); +} + +- (void)testFailingMatches { + expectFailureMessage(@"expected to find object in collection that satisfies predicate", ^{ + expect(@[@1]).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((nil)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((@3)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); +} + +- (void)testNegativeCases { + NSArray *orderIndifferentArray = @[@"puppies", @"kittens", @"turtles"]; + expect(orderIndifferentArray).toNot(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"armadillos"]; + })); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..8b954fe --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m @@ -0,0 +1,67 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainTest : XCTestCase + +@end + +@implementation ObjCContainTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1)); + expect(array).toNot(contain(@"HI")); + expect(@"String").to(contain(@"Str")); + expect(@"Other").toNot(contain(@"Str")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to contain <3>, got <(1, 2)>", ^{ + expect((@[@1, @2])).to(contain(@3)); + }); + expectFailureMessage(@"expected to not contain <2>, got <(1, 2)>", ^{ + expect((@[@1, @2])).toNot(contain(@2)); + }); + + expectFailureMessage(@"expected to contain , got ", ^{ + expect(@"la").to(contain(@"hi")); + }); + expectFailureMessage(@"expected to not contain , got ", ^{ + expect(@"hihihi").toNot(contain(@"hi")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to contain <3>, got ", ^{ + expect(nil).to(contain(@3)); + }); + expectNilFailureMessage(@"expected to not contain <3>, got ", ^{ + expect(nil).toNot(contain(@3)); + }); + + expectNilFailureMessage(@"expected to contain , got ", ^{ + expect(nil).to(contain(@"hi")); + }); + expectNilFailureMessage(@"expected to not contain , got ", ^{ + expect(nil).toNot(contain(@"hi")); + }); +} + +- (void)testVariadicArguments { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1, @2)); + expect(array).toNot(contain(@"HI", @"whale")); + expect(@"String").to(contain(@"Str", @"ng")); + expect(@"Other").toNot(contain(@"Str", @"Oth")); + + + expectFailureMessage(@"expected to contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).to(contain(@"a", @"bar")); + }); + + expectFailureMessage(@"expected to not contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).toNot(contain(@"a", @"b")); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEndWithTest : XCTestCase + +@end + +@implementation ObjCEndWithTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(@"hello world!").to(endWith(@"world!")); + expect(@"hello world!").toNot(endWith(@"hello")); + expect(array).to(endWith(@2)); + expect(array).toNot(endWith(@1)); + expect(@1).toNot(contain(@"foo")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to end with , got ", ^{ + expect(@"hello world!").to(endWith(@"?")); + }); + expectFailureMessage(@"expected to not end with , got ", ^{ + expect(@"hello world!").toNot(endWith(@"!")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to end with <1>, got ", ^{ + expect(nil).to(endWith(@1)); + }); + expectNilFailureMessage(@"expected to not end with <1>, got ", ^{ + expect(nil).toNot(endWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..9d1361e --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m @@ -0,0 +1,94 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEqualTest : XCTestCase + +@end + +@implementation ObjCEqualTest + +- (void)testPositiveMatches { + expect(@1).to(equal(@1)); + expect(@1).toNot(equal(@2)); + expect(@1).notTo(equal(@2)); + expect(@"hello").to(equal(@"hello")); + expect("hello").to(equal("hello")); + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 10))); + expect(NSMakeRange(0, 10)).toNot(equal(NSMakeRange(0, 5))); + expect((NSInteger)1).to(equal((NSInteger)1)); + expect((NSInteger)1).toNot(equal((NSInteger)2)); + expect((NSUInteger)1).to(equal((NSUInteger)1)); + expect((NSUInteger)1).toNot(equal((NSUInteger)2)); + expect(0).to(equal(0)); + expect(1).to(equal(1)); + expect(1).toNot(equal(2)); + expect(1.0).to(equal(1.0)); // Note: not recommended, use beCloseTo() instead + expect(1.0).toNot(equal(2.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).to(equal((float)1.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).toNot(equal((float)2.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).to(equal((double)1.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).toNot(equal((double)2.0)); // Note: not recommended, use beCloseTo() instead + expect((long long)1).to(equal((long long)1)); + expect((long long)1).toNot(equal((long long)2)); + expect((unsigned long long)1).to(equal((unsigned long long)1)); + expect((unsigned long long)1).toNot(equal((unsigned long long)2)); +} + +- (void)testNimbleCurrentlyBoxesNumbersWhichAllowsImplicitTypeConversions { + expect(1).to(equal(1.0)); + expect((long long)1).to(equal((unsigned long long)1)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(@1).to(equal(@2)); + }); + expectFailureMessage(@"expected to not equal <1>, got <1>", ^{ + expect(@1).toNot(equal(@1)); + }); + expectFailureMessage(@"expected to not equal , got ", ^{ + expect("bar").toNot(equal("bar")); + }); + expectFailureMessage(@"expected to equal , got ", ^{ + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 5))); + }); + + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSInteger)1).to(equal((NSInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSUInteger)1).to(equal((NSUInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1).to(equal(2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1.0).to(equal(2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((float)1.0).to(equal((float)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((double)1.0).to(equal((double)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((long long)1.0).to(equal((long long)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((unsigned long long)1.0).to(equal((unsigned long long)2.0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(NULL).to(equal(NULL)); + }); + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(nil).to(equal(nil)); + }); + expectNilFailureMessage(@"expected to not equal , got ", ^{ + expect(nil).toNot(equal(nil)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m @@ -0,0 +1,174 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCHaveCountTest : XCTestCase + +@end + +@implementation ObjCHaveCountTest + +- (void)testHaveCountForNSArray { + expect(@[@1, @2, @3]).to(haveCount(@3)); + expect(@[@1, @2, @3]).notTo(haveCount(@1)); + + expect(@[]).to(haveCount(@0)); + expect(@[@1]).notTo(haveCount(@0)); + + expect(@[@1, @2, @3]).to(haveCount(3)); + expect(@[@1, @2, @3]).notTo(haveCount(1)); + + expect(@[]).to(haveCount(0)); + expect(@[@1]).notTo(haveCount(0)); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSDictionary { + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@1)); + + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSHashtable { + NSHashTable *const table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + [table addObject:@2]; + [table addObject:@3]; + + expect(table).to(haveCount(@3)); + expect(table).notTo(haveCount(@1)); + + expect(table).to(haveCount(3)); + expect(table).notTo(haveCount(1)); + + NSString *msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(@1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(@3)); + }); + + + msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSSet { + NSSet *const set = [NSSet setWithArray:@[@1, @2, @3]]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSIndexSet { + NSIndexSet *const set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForUnsupportedTypes { + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(6)); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m @@ -0,0 +1,33 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCMatchTest : XCTestCase + +@end + +@implementation ObjCMatchTest + +- (void)testPositiveMatches { + expect(@"11:14").to(match(@"\\d{2}:\\d{2}")); + expect(@"hello").toNot(match(@"\\d{2}:\\d{2}")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(@"hello").to(match(@"\\d{2}:\\d{2}")); + }); + expectFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got <11:22>", ^{ + expect(@"11:22").toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).to(match(@"\\d{2}:\\d{2}")); + }); + expectNilFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..9b5a378 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m @@ -0,0 +1,178 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCRaiseExceptionTest : XCTestCase + +@end + +@implementation ObjCRaiseExceptionTest + +- (void)testPositiveMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ @throw exception; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException().named(NSInvalidArgumentException)); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food")); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"})); + + expectAction(^{ }).toNot(raiseException()); +} + +- (void)testPositiveMatchesWithBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); +} + +- (void)testNegativeMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + + expectFailureMessage(@"expected to raise any exception, got no exception", ^{ + expectAction(^{ }).to(raiseException()); + }); + + expectFailureMessage(@"expected to raise exception with name , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(@"foo")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"cakes")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason with userInfo <{k = v;}>, got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"k": @"v"})); + }); + + expectFailureMessage(@"expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }", ^{ + expectAction(^{ [exception raise]; }).toNot(raiseException()); + }); +} + +- (void)testNegativeMatchesWithPassingBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectFailureMessage(@"expected to raise exception that satisfies block, got no exception", ^{ + expect(exception).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"LOL")); + })); + }); + + NSString *outerFailureMessage = @"expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).toNot(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(@"foo"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"bar"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); +} + +- (void)testNegativeMatchesWithNegativeBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + NSString *outerFailureMessage; + + NSString *const innerFailureMessage = @"expected to equal , got "; + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m new file mode 100644 index 0000000..5b38b83 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAllOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAllOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAllOf(equal(@2), beLessThan(@3))); + expect(@2).toNot(satisfyAllOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAllOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).toNot(satisfyAllOf(beTrue(), beFalse())); + expect(@YES).toNot(satisfyAllOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAllOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match all of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, and {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAllOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAllOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAllOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAnyOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAnyOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAnyOf(equal(@2), equal(@3))); + expect(@2).toNot(satisfyAnyOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAnyOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).to(satisfyAnyOf(beTrue(), beFalse())); + expect(@YES).to(satisfyAnyOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAnyOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match one of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, or {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAnyOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAnyOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAnyOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m @@ -0,0 +1,21 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSyncTest : XCTestCase + +@end + +@implementation ObjCSyncTest + +- (void)testFailureExpectation { + expectFailureMessage(@"fail() always fails", ^{ + fail(); + }); + + expectFailureMessage(@"This always fails", ^{ + failWithMessage(@"This always fails"); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m @@ -0,0 +1,52 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCUserDescriptionTest : XCTestCase + +@end + +@implementation ObjCUserDescriptionTest + +- (void)testToWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to equal <2>, got <1>", ^{ + expect(@1).toWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).toNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testNotToWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).notToWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToEventuallyWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to eventually equal <2>, got <1>", ^{ + expect(@1).toEventuallyWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToEventuallyNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toEventuallyNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToNotEventuallyWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toNotEventuallyWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +@end diff --git a/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m @@ -0,0 +1,31 @@ +@import XCTest; +@import Nimble; + +@interface ObjcStringersTest : XCTestCase + +@end + +@implementation ObjcStringersTest + +- (void)testItCanStringifyArrays { + NSArray *array = @[@1, @2, @3]; + NSString *result = NMBStringify(array); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItCanStringifyIndexSets { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + NSString *result = NMBStringify(indexSet); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItRoundsLongDecimals { + NSNumber *num = @291.123782163; + NSString *result = NMBStringify(num); + + expect(result).to(equal(@"291.1238")); +} + +@end diff --git a/Carthage/Checkouts/Nimble/script/release b/Carthage/Checkouts/Nimble/script/release new file mode 100755 index 0000000..f61c0dc --- /dev/null +++ b/Carthage/Checkouts/Nimble/script/release @@ -0,0 +1,187 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Nimble +PODSPEC=Nimble.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=/tmp/nimble.release.notes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "---------------- Released as $VERSION_TAG ----------------" +echo + +echo +echo "Pushing to pod trunk..." + +# NOTE: remove allow-warnings after v9.0.0 of Nimble +$POD trunk push "$PODSPEC" --allow-warnings + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for GitHub styling." +echo " - Announce!" + +open "https://github.com/Quick/Nimble/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Nimble/test b/Carthage/Checkouts/Nimble/test new file mode 100755 index 0000000..0766351 --- /dev/null +++ b/Carthage/Checkouts/Nimble/test @@ -0,0 +1,156 @@ +#!/bin/bash + +GREEN="\033[0;32m" +CLEAR="\033[0m" + +if which xcodebuild > /dev/null; then + echo -e "Gathering ${GREEN}xcodebuild sdk versions${CLEAR}..." + BUILD_DIR=`pwd`/build + LATEST_IOS_SDK_VERSION=`xcodebuild -showsdks | grep iphonesimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_TVOS_SDK_VERSION=`xcodebuild -showsdks | grep appletvsimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_MACOS_SDK_VERSION=`xcodebuild -showsdks | grep 'macosx' | cut -d ' ' -f 3 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + BUILD_IOS_SDK_VERSION=${NIMBLE_BUILD_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + RUNTIME_IOS_SDK_VERSION=${NIMBLE_RUNTIME_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + BUILD_TVOS_SDK_VERSION=${NIMBLE_BUILD_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + RUNTIME_TVOS_SDK_VERSION=${NIMBLE_RUNTIME_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + BUILD_MACOS_SDK_VERSION=${NIMBLE_BUILD_MACOS_SDK_VERSION:-$LATEST_MACOS_SDK_VERSION} +fi + +set -e + +function color_if_overridden { + local actual=$1 + local env_var=$2 + if [ -z "$env_var" ]; then + printf "$actual" + else + printf "$GREEN$actual$CLEAR" + fi +} + +function print_env { + echo "=== Environment ===" + echo " iOS:" + echo " Latest iOS SDK: $LATEST_IOS_SDK_VERSION" + echo " Building with iOS SDK: `color_if_overridden $BUILD_IOS_SDK_VERSION $NIMBLE_BUILD_IOS_SDK_VERSION`" + echo " Running with iOS SDK: `color_if_overridden $RUNTIME_IOS_SDK_VERSION $NIMBLE_RUNTIME_IOS_SDK_VERSION`" + echo + echo " tvOS:" + echo " Latest tvOS SDK: $LATEST_TVOS_SDK_VERSION" + echo " Building with tvOS SDK: `color_if_overridden $BUILD_TVOS_SDK_VERSION $NIMBLE_BUILD_TVOS_SDK_VERSION`" + echo " Running with tvOS SDK: `color_if_overridden $RUNTIME_TVOS_SDK_VERSION $NIMBLE_RUNTIME_TVOS_SDK_VERSION`" + echo + echo " macOS:" + echo " Latest macOS SDK: $LATEST_MACOS_SDK_VERSION" + echo " Building with macOS SDK: `color_if_overridden $BUILD_MACOS_SDK_VERSION $NIMBLE_BUILD_MACOS_SDK_VERSION`" + echo + echo "======= END =======" + echo +} + +function run { + echo -e "$GREEN==>$CLEAR $@" + "$@" +} + +function test_ios { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPad Air,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building + + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPhone 5s,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_tvos { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-tvOS" -configuration "Debug" -sdk "appletvsimulator$BUILD_TVOS_SDK_VERSION" -destination "name=Apple TV 1080p,OS=$RUNTIME_TVOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_macos { + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-macOS" -configuration "Debug" -sdk "macosx$BUILD_MACOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_podspec { + echo "Gathering CocoaPods installation information..." + run bundle exec pod --version + echo "Linting podspec..." + # Note: remove `--allow-warnings` once old Matcher API has been removed + run bundle exec pod lib lint Nimble.podspec --allow-warnings +} + +function test_swiftpm { + if [ -d .build ]; then + run swift build --clean + fi + run swift build && swift test +} + +function test_swiftpm_docker { + run docker build -t nimble-tests -f Dockerfile.test --no-cache . + run docker run -it --privileged=true nimble-tests +} + +function test() { + test_ios + test_tvos + test_macos + + if which swift-test; then + test_swiftpm + else + echo "Not testing with the Swift Package Manager because swift-test is not installed" + fi + + if which docker; then + test_swiftpm_docker + else + echo "Not testing linux in docker container since docker is not in PATH!" + fi +} + +function clean { + run rm -rf ~/Library/Developer/Xcode/DerivedData\; true +} + +function help { + echo "Usage: $0 COMMANDS" + echo + echo "COMMANDS:" + echo " all - Runs the all tests of macos, ios and tvos" + echo " clean - Cleans the derived data directory of Xcode. Assumes default location" + echo " help - Displays this help" + echo " ios - Runs the tests as an iOS device" + echo " macos - Runs the tests on macOS 10.10 (Yosemite and newer only)" + echo " podspec - Runs pod lib lint against the podspec to detect breaking changes" + echo " swiftpm - Runs the tests built by the Swift Package Manager" + echo " swiftpm_docker - Runs the tests built by the Swift Package Manager in a docker linux container" + echo " tvos - Runs the tests as an tvOS device" + echo + exit 1 +} + +function main { + print_env + for arg in $@ + do + case "$arg" in + clean) clean ;; + ios) test_ios ;; + tvos) test_tvos ;; + macos) test_macos ;; + podspec) test_podspec ;; + test) test ;; + all) test ;; + swiftpm) test_swiftpm ;; + swiftpm_docker) test_swiftpm_docker ;; + help) help ;; + esac + done + + if [ $# -eq 0 ]; then + clean + test + fi +} + +main $@ diff --git a/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..ebe5a2b --- /dev/null +++ b/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Quick/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Quick/.gitignore b/Carthage/Checkouts/Quick/.gitignore new file mode 100644 index 0000000..6566a42 --- /dev/null +++ b/Carthage/Checkouts/Quick/.gitignore @@ -0,0 +1,66 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +.build/ +# Package.pins +# Package.resolved + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +# Mac OS X +.DS_Store + +# Quick +Quick.framework.zip diff --git a/Carthage/Checkouts/Quick/.gitmodules b/Carthage/Checkouts/Quick/.gitmodules new file mode 100644 index 0000000..cffbed0 --- /dev/null +++ b/Carthage/Checkouts/Quick/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Externals/Nimble"] + path = Externals/Nimble + url = https://github.com/Quick/Nimble.git diff --git a/Carthage/Checkouts/Quick/.hound.yml b/Carthage/Checkouts/Quick/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Quick/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Quick/.swift-version b/Carthage/Checkouts/Quick/.swift-version new file mode 100644 index 0000000..8c50098 --- /dev/null +++ b/Carthage/Checkouts/Quick/.swift-version @@ -0,0 +1 @@ +3.1 diff --git a/Carthage/Checkouts/Quick/.swiftlint.yml b/Carthage/Checkouts/Quick/.swiftlint.yml new file mode 100644 index 0000000..79cda08 --- /dev/null +++ b/Carthage/Checkouts/Quick/.swiftlint.yml @@ -0,0 +1,8 @@ +disabled_rules: + - line_length + - type_name + - function_body_length + - identifier_name +included: + - Sources + - Tests diff --git a/Carthage/Checkouts/Quick/.travis.yml b/Carthage/Checkouts/Quick/.travis.yml new file mode 100644 index 0000000..c33dc20 --- /dev/null +++ b/Carthage/Checkouts/Quick/.travis.yml @@ -0,0 +1,52 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + env: + - PLATFORM=macos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + osx_image: xcode9.3 + env: + - PLATFORM=macos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + osx_image: xcode9.3 + env: + - PLATFORM=macos_static + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=ios + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=tvos + - XCODE_ACTION="build-for-testing test-without-building" + - os: osx + env: + - PLATFORM=swiftpm + - os: osx + osx_image: xcode9.3 + env: + - PLATFORM=swiftpm + - os: osx + env: + - PODSPEC=1 + - os: linux + sudo: required + dist: trusty + - os: linux + sudo: required + dist: trusty + env: + - SWIFT_VERSION=4.1 +install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./script/travis-install-macos; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./script/travis-install-linux; fi + - if [[ "$PODSPEC" ]]; then gem install bundler; bundle install; fi +script: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./script/travis-script-macos; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./script/travis-script-linux; fi + - if [[ "$PODSPEC" ]]; then danger; fi diff --git a/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md b/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f82f39a --- /dev/null +++ b/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [quickorg@icloud.com](mailto:quickorg@icloud.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/Carthage/Checkouts/Quick/CONTRIBUTING.md b/Carthage/Checkouts/Quick/CONTRIBUTING.md new file mode 100644 index 0000000..e8e32c1 --- /dev/null +++ b/Carthage/Checkouts/Quick/CONTRIBUTING.md @@ -0,0 +1,111 @@ + + +**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* + +- [Welcome to Quick!](#welcome-to-quick!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + - [Creating a Release](#creating-a-release) + + + +# Welcome to Quick! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Quick should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Quick / Nimble (eg - v0.7.0 or git sha `7d0b8c21357839a8c5228863b77faecf709254a9`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- After cloning the repository, run `git submodule update --init` to pull the Nimble submodule. +- Use `Quick.xcworkspace` to work on Quick. The workspace includes + Nimble, which is used in Quick's tests. + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of both Quick + and Nimble pass before submitting your pull request. You can run all + the iOS and OS X unit tests using `rake`. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. See `QuickSpec.m` for an example. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + Pull requests should be issued from personal forks. The Quick repo + should be reserved for long-running feature branches. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +Read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for more in depth guidelines. + +## Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Quick/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Announce! diff --git a/Carthage/Checkouts/Quick/Dangerfile b/Carthage/Checkouts/Quick/Dangerfile new file mode 100644 index 0000000..719de60 --- /dev/null +++ b/Carthage/Checkouts/Quick/Dangerfile @@ -0,0 +1,53 @@ +# set the number of lines that must be changed before this classifies as a 'Big PR' +@SDM_DANGER_BIG_PR_LINES = 50 + +# set the files to watch and fail if there are changes +@SDM_DANGER_IMMUTABLE_FILES = ['LICENSE', 'CONTRIBUTING.md', 'CODE_OF_CONDUCT.md'] + +# Sometimes it's a README fix, or something like that which is trivial +not_declared_trivial = !(github.pr_title.include? "#trivial") +has_app_changes = !git.modified_files.grep(/Sources/).empty? +no_test_modify = git.modified_files.grep(/Tests/).empty? + +# Warns when changing source files +if has_app_changes && not_declared_trivial && no_test_modify + warn("Need to add an unit test if you're modifying swift source") +end + +# determine if any of the files were modified +def did_modify(files_array) + did_modify_files = false + files_array.each do |file_name| + if git.modified_files.include?(file_name) || git.deleted_files.include?(file_name) + did_modify_files = true + end + end + return did_modify_files +end + +# Fail if changes to immutable files, such as License or CoC +fail('Do not modify the license or Code of Conduct') if did_modify(@SDM_DANGER_IMMUTABLE_FILES) + +# Make it more obvious that a PR is a work in progress and shouldn't be merged yet +warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" + +# Warn when there is a big PR +warn("Big PR") if git.lines_of_code > @SDM_DANGER_BIG_PR_LINES + +# Make a note about contributors not in the organization +unless github.api.organization_member?('Quick', github.pr_author) + # Pay extra attention if they modify the podspec + if git.modified_files.include?("*.podspec") + warn "External contributor has edited the Podspec file" + end +end + +# Mainly to encourage writing up some reasoning about the PR, rather than +# just leaving a title +if github.pr_body.length < 5 + warn "Please provide a summary in the Pull Request description" +end + +swiftlint.config_file = '.swiftlint.yml' +swiftlint.lint_files + diff --git a/Carthage/Checkouts/Quick/Documentation/README.md b/Carthage/Checkouts/Quick/Documentation/README.md new file mode 100644 index 0000000..ea28bd1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/README.md @@ -0,0 +1,7 @@ +# Documentation + +- [English](en-us/README.md) +- [日本語](ja/README.md) +- [中文](zh-cn/README.md) +- [pt-br](pt-br/README.md) +- [한국어](ko-kr/README.md) diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md b/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md new file mode 100644 index 0000000..fc7915b --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md @@ -0,0 +1,220 @@ +# Effective Tests Using XCTest: Arrange, Act, and Assert + +Whether you're using XCTest, Quick, or another testing framework, you can write +effective unit tests by following a simple pattern: + +1. Arrange +2. Act +3. Assert + +## Using Arrange, Act, and Assert + +For example, let's look at a simple class called `Banana`: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +Let's verify the `Banana.peel()` method does what it's supposed to: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## Using Clear Test Names + +Our `testPeel()` makes sure that, if the `Banana.peel()` method ever +stops working right, we'll know. This usually happens when our application +code changes, which either means: + +1. We accidentally broke our application code, so we have to fix the application code +2. We changed how our application code works--maybe because we're adding a new + feature--so we have to change the test code + +If our tests start breaking, how do we know which one of these cases applies? It might +surprise you that **the name of the test** is our best indication. Good test names: + +1. Are clear about what is being tested. +2. Are clear about when the test should pass or fail. + +Is our `testPeel()` method clearly named? Let's make it clearer: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +The new name: + +1. Is clear about what is being tested: `testPeel` indicates it's the `Banana.peel()` method. +2. Is clear about when the test should pass: `makesTheBananaEdible` indicates the + banana is edible once the method has been called. + +## Testing Conditions + +Let's say we want to offer people bananas, using a function called `offer()`: + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +Our application code does one of two things: + +1. Either it offers a banana that's already been peeled... +2. ...or it offers an unpeeled banana. + +Let's write tests for these two cases: + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +Our test names clearly indicate the **conditions** under which our tests should pass: +in the case that `whenTheBananaIsPeeled`, `offer()` should `offersTheBanana`. And if +the banana isn't peeled? Well, we have a test for that, too! + +Notice that we have one test per `if` statement in our application code. +This is a great pattern when writing tests: it makes sure every set of conditions +is tested. If one of those conditions no longer works, or needs to be changed, we'll know +exactly which test needs to be looked at. + +## Shorter "Arrange" Steps with `XCTestCase.setUp()` + +Both of our `OfferTests` tests contain the same "Arrange" code: they both +create a banana. We should move that code into a single place. Why? + +1. As-is, if we change the `Banana` initializer, we'll have to change every test that creates a banana. +2. Our test methods will be shorter--which is a good thing if (and **only if**) that makes + the tests easier to read. + +Let's move the `Banana` initialization into the `XCTestCase.setUp()` method, which is called +once before every test method. + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## Sharing "Arrange" Code Across Multiple Tests + +If you find yourself using the same "arrange" steps across multiple tests, +you may want to define a helper function within your test target: + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> Use a function to define your helpers: functions can't be subclassed, nor + can they retain any state. Subclassing and mutable state can make your tests + harder to read. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md b/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md new file mode 100644 index 0000000..02ae0c0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md @@ -0,0 +1,87 @@ +# Don't Test Code, Instead Verify Behavior + +Tests should only fail if the application **behaves differently**. +They should test *what* the application code does, not *how* it does those things. + +- Tests that verify *what* an application does are **behavioral tests**. +- Tests that break if the application code changes, even if the behavior + remains the same, are **brittle tests**. + +Let's say we have a banana database, called `GorillaDB`. +`GorillaDB` is a key-value store for bananas. We can save bananas: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +And we can restore bananas from disk later: + +```swift +let banana = database.load(key: "my-banana") +``` + +## Brittle Tests + +How can we test this behavior? One way would be to check the size of the database +after we save a banana: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +Imagine, however, that the source code of `GorillaDB` changes. In order to make +reading bananas from the database faster, it maintains a cache of the most frequently +used bananas. `GorillaDB.size` grows as the size of the cache grows, and our test fails: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## Behavioral Tests + +The key to writing behavioral tests is determining exactly what you're expecting +your application code to do. + +In the context of our `testSave_savesTheBananaToTheDatabase` test: what is the +behavior we expect when we "save" a banana to the database? "Saving" implies, to me, +that we can load it later. So instead of testing that the size of the database increases, +we should test that we can load a banana. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +The key to writing behavioral tests is asking: + +- What exactly should this application code do? +- Is my test verifying *only* that behavior? + Or could it fail due to other aspects of how the code works? diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md b/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md new file mode 100644 index 0000000..7792963 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md @@ -0,0 +1,103 @@ +# Configuring How Quick Behaves + +You can customize how Quick behaves by subclassing `QuickConfiguration` and +overriding the `QuickConfiguration.Type.configure()` class method: + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +Projects may include several configurations. Quick does not make any +guarantee about the order in which those configurations are executed. + +## Adding Global `beforeEach` and `afterEach` Closures + +Using `QuickConfiguration.beforeEach` and `QuickConfiguration.afterEach`, you +can specify closures to be run before or after *every* example in a test suite: + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +In addition, Quick allows you to access metadata regarding the current +example being run: + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md b/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md new file mode 100644 index 0000000..3de82c5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md @@ -0,0 +1,28 @@ +# Installing Quick File Templates + +The Quick repository includes file templates for both Swift and +Objective-C specs. + +## Alcatraz + +Quick templates can be installed via [Alcatraz](https://github.com/supermarin/Alcatraz), +a package manager for Xcode. Just search for the templates from the +Package Manager window. + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Manually via the Rakefile + +To manually install the templates, just clone the repository and +run the `templates:install` rake task: + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +Uninstalling is easy, too: + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md b/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md new file mode 100644 index 0000000..258956f --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md @@ -0,0 +1,157 @@ +# Installing Quick + +>Before starting, check [here](../../README.md#swift-version) which versions of Quick and Nimble are compatible with your version of Swift. + +Quick provides the syntax to define examples and example groups. Nimble +provides the `expect(...).to` assertion syntax. You may use either one, +or both, in your tests. + +There are three recommended ways of linking Quick to your tests: + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift Package Manager (experimental)](#swift-package-manager) + +Choose one and follow the instructions below. Once you've completed them, +you should be able to `import Quick` from within files in your test target. + +## Git Submodules + +To link Quick and Nimble using Git submodules: + +1. Add submodule for Quick. +2. If you don't already have a `.xcworkspace` for your project, create one. ([Here's how](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. Add `Quick.xcodeproj` to your project's `.xcworkspace`. +4. Add `Nimble.xcodeproj` to your project's `.xcworkspace`. It exists in `path/to/Quick/Externals/Nimble`. By adding Nimble from Quick's dependencies (as opposed to adding directly as a submodule), you'll ensure that you're using the correct version of Nimble for whatever version of Quick you're using. +5. Link `Quick.framework` and `Nimble.framework` in your test target's + "Link Binary with Libraries" build phase. + +First, if you don't already have one, create a directory for your Git submodules. +Let's assume you have a directory named `Vendor`. + +**Step One:** Download Quick and Nimble as Git submodules: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step Two:** Add the `Quick.xcodeproj` and `Nimble.xcodeproj` files downloaded above to +your project's `.xcworkspace`. For example, this is `Guanaco.xcworkspace`, the +workspace for a project that is tested using Quick and Nimble: + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step Three:** Link the `Quick.framework` during your test target's +`Link Binary with Libraries` build phase. You should see two +`Quick.frameworks`; one is for macOS, and the other is for iOS. + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +Do the same for the `Nimble.framework`, and you're done! + +**Updating the Submodules:** If you ever want to update the Quick +or Nimble submodules to latest version, enter the Quick directory +and pull from the master repository: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +Your Git repository will track changes to submodules. You'll want to +commit the fact that you've updated the Quick submodule: + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Cloning a Repository that Includes a Quick Submodule:** After other people +clone your repository, they'll have to pull down the submodules as well. +They can do so by running the `git submodule update` command: + +```sh +git submodule update --init --recursive +``` + +You can read more about Git submodules [here](http://git-scm.com/book/en/Git-Tools-Submodules). + +## CocoaPods + +First, update CocoaPods to Version 0.36.0 or newer, which is necessary to install CocoaPods using Swift. + +Then, add Quick and Nimble to your Podfile. Additionally, the ```use_frameworks!``` line is necessary for using Swift in CocoaPods: + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +Finally, download and link Quick and Nimble to your tests: + +```sh +pod install +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +As test targets do not have the "Embedded Binaries" section, the frameworks must +be added to the target's "Link Binary With Libraries" as well as a "Copy Files" build phase +to copy them to the target's Frameworks destination. + + > As Carthage builds dynamic frameworks, you will need a valid code signing identity set up. + +1. Add Quick to your [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate): + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. Run `carthage update`. +3. From your `Carthage/Build/[platform]/` directory, add both Quick and Nimble to your test target's "Link Binary With Libraries" build phase: + ![](http://i.imgur.com/pBkDDk5.png) + +4. For your test target, create a new build phase of type "Copy Files": + ![](http://i.imgur.com/jZATIjQ.png) + +5. Set the "Destination" to "Frameworks", then add both frameworks: + ![](http://i.imgur.com/rpnyWGH.png) + +This is not "the one and only way" to use Carthage to manage dependencies. +For further reference check out the [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md). + +## [Swift Package Manager](https://github.com/apple/swift-package-manager) +With the advent of the [swift.org](https://swift.org) open-source project, Swift now has an official, though nascent, package manager tool. Notably, this provides the possibility of using Quick on non-Apple platforms for the first time. Initial steps have been taken to allow using Quick to test projects using the Swift Package Manager, although frequent breakage is expected at this point since the tool is still under heavy development. + +Until further documentation has been written, the following repository may be useful as an example of how Quick can be declared as a dependency in a `Package.swift` file for SwiftPM: + +https://github.com/Quick/QuickOnLinuxExample + +### (Not Recommended) Running Quick Specs on a Physical iOS Device + +In order to run specs written in Quick on device, you need to add `Quick.framework` and +`Nimble.framework` as `Embedded Binaries` to the `Host Application` of the +test target. After adding a framework as an embedded binary, Xcode will +automatically link the host app against the framework. + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md b/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md new file mode 100644 index 0000000..65d7eba --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md @@ -0,0 +1,28 @@ +# More Resources + +## Examples of Quick Specs + +Quick is used by many companies, open-source projects, and individuals, +including [GitHub](https://github.com/github) and +[ReactiveCocoa](https://github.com/ReactiveCocoa). For examples, check out: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## More on Unit Testing for OS X and iOS Apps + +- **[Quality Coding](http://qualitycoding.org/)**: + A blog on iOS development that focuses on unit testing. +- **[OCMock Tutorials](http://ocmock.org/support/)**: + Use OCMock when you need "fake objects" in your tests. +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**: + Use this library to test code that sends requests to, and receives responses from, the Internet. +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + See [the Nimble documentation](https://github.com/Quick/Nimble) for instructions on how to write + custom matchers in Nimble. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md b/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md new file mode 100644 index 0000000..db68c40 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md @@ -0,0 +1,106 @@ +# Clearer Tests Using Nimble Assertions + +When code doesn't work the way it's supposed to, unit tests should make it +**clear** exactly what's wrong. + +Take the following function which, given a bunch of monkeys, only returns +the silly monkeys in the bunch: + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +Now let's say we have a unit test for this function: + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +The test fails with the following failure message: + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +The failure message leaves a lot to be desired. It leaves us wondering, +"OK, so something that should have been true was false--but what?" +That confusion slows us down, since we now have to spend time deciphering test code. + +## Better Failure Messages, Part 1: Manually Providing `XCTAssert` Failure Messages + +`XCTAssert` assertions allow us to specify a failure message of our own, which certainly helps: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +But we have to write our own failure message. + +## Better Failure Messages, Part 2: Nimble Failure Messages + +Nimble makes your test assertions, and their failure messages, easier to read: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +We don't have to write our own failure message--the one provided by Nimble +is already very readable: + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: verySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +The failure message makes it clear what's wrong: we were expecting `kiki` to be included +in the result of `silliest()`, but the result only contains `jane`. Now that we know +exactly what's wrong, it's easy to fix the issue: + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble provides many different kind of assertions, each with great failure +messages. And unlike `XCTAssert`, you don't have to type your own failure message +every time. + +For the full list of Nimble assertions, check out the [Nimble README](https://github.com/Quick/Nimble). +Below is just a sample, to whet your appetite: + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md b/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md new file mode 100644 index 0000000..dd8db21 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md @@ -0,0 +1,491 @@ +# Organized Tests with Quick Examples and Example Groups + +Quick uses a special syntax to define **examples** and **example groups**. + +In *[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)*, +we learned that a good test method name is crucial--when a test starts failing, it's +the best way to determine whether we have to fix the application code or update the test. + +Quick examples and example groups serve two purposes: + +1. They encourage you to write descriptive test names. +2. They greatly simplify the test code in the "arrange" step of your tests. + +## Examples Using `it` + +Examples, defined with the `it` function, use assertions to demonstrate +how code should behave. These are like test methods in XCTest. + +`it` takes two parameters: the name of the example, and a closure. +The examples below specify how the `Sea.Dolphin` class should behave. +A new dolphin should be smart and friendly: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +Use descriptions to make it clear what your examples are testing. +Descriptions can be of any length and use any character, including +characters from languages besides English, or even emoji! :v: :sunglasses: + +## Example Groups Using `describe` and `context` + +Example groups are logical groupings of examples. Example groups can share +setup and teardown code. + +### Describing Classes and Methods Using `describe` + +To specify the behavior of the `Dolphin` class's `click` method--in +other words, to test the method works--several `it` examples can be +grouped together using the `describe` function. Grouping similar +examples together makes the spec easier to read: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +When these two examples are run in Xcode, they'll display the +description from the `describe` and `it` functions: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +Again, it's clear what each of these examples is testing. + +### Sharing Setup/Teardown Code Using `beforeEach` and `afterEach` + +Example groups don't just make the examples clearer, they're also useful +for sharing setup and teardown code among examples in a group. + +In the example below, the `beforeEach` function is used to create a brand +new instance of a dolphin and its click before each example in the group. +This ensures that both are in a "fresh" state for every example: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +Sharing setup like this might not seem like a big deal with the +dolphin example, but for more complicated objects, it saves a lot +of typing! + +To execute code *after* each example, use `afterEach`. + +### Specifying Conditional Behavior Using `context` + +Dolphins use clicks for echolocation. When they approach something +particularly interesting to them, they release a series of clicks in +order to get a better idea of what it is. + +The tests need to show that the `click` method behaves differently in +different circumstances. Normally, the dolphin just clicks once. But when +the dolphin is close to something interesting, it clicks several times. + +This can be expressed using `context` functions: one `context` for the +normal case, and one `context` for when the dolphin is close to +something interesting: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +Strictly speaking, the `context` keyword is a synonym for `describe`, +but thoughtful use will make your spec easier to understand. + +### Test Readability: Quick and XCTest + +In [Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md), +we looked at how one test per condition was a great way to organize test code. +In XCTest, that leads to long test method names: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Using Quick, the conditions are much easier to read, and we can perform setup +for each example group: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## Temporarily Disabling Examples or Groups + +You can temporarily disable examples or example groups that don't pass yet. +The names of the examples will be printed out along with the test results, +but they won't be run. + +You can disable an example or group by prepending `x`: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## Temporarily Running a Subset of Focused Examples + +Sometimes it helps to focus on only one or a few examples. Running one +or two examples is faster than the entire suite, after all. You can +run only one or two by using the `fit` function. You can also focus a +group of examples using `fdescribe` or `fcontext`: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## Global Setup/Teardown Using `beforeSuite` and `afterSuite` + +Some test setup needs to be performed before *any* examples are +run. For these cases, use `beforeSuite` and `afterSuite`. + +In the example below, a database of all the creatures in the ocean is +created before any examples are run. That database is torn down once all +the examples have finished: + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +You can specify as many `beforeSuite` and `afterSuite` as you like. All +`beforeSuite` closures will be executed before any tests run, and all +`afterSuite` closures will be executed after all the tests are finished. +There is no guarantee as to what order these closures will be executed in. + +## Accessing Metadata for the Current Example + +There may be some cases in which you'd like the know the name of the example +that is currently being run, or how many have been run so far. Quick provides +access to this metadata in `beforeEach` and `afterEach` closures. + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md b/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md new file mode 100644 index 0000000..3fb6bdc --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md @@ -0,0 +1,57 @@ +# Using Quick in Objective-C + +Quick works equally well in both Swift and Objective-C. + +There are two notes to keep in mind when using Quick in Objective-C, +however, which are described below. + +## The Optional Shorthand Syntax + +Importing Quick in an Objective-C file defines macros named `it` and +`itShouldBehaveLike`, as well as functions like `context()` and `describe()`. + +If the project you are testing also defines symbols with these names, you may +encounter confusing build failures. In that case, you can avoid namespace +collision by turning off Quick's optional "shorthand" syntax: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +You must define the `QUICK_DISABLE_SHORT_SYNTAX` macro *before* +importing the Quick header. + +Alternatively, you may define the macro in your test target's build configuration: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## Your Test Target Must Include At Least One Swift File + +The Swift stdlib will not be linked into your test target, and thus +Quick will fail to execute properly, if your test target does not contain +*at least one* Swift file. + +Without at least one Swift file, your tests will exit prematurely with +the following error: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +To fix the problem, add a blank file called `SwiftSpec.swift` to your test target: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> For more details on this issue, see https://github.com/Quick/Quick/issues/164. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/README.md b/Carthage/Checkouts/Quick/Documentation/en-us/README.md new file mode 100644 index 0000000..d03f633 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/README.md @@ -0,0 +1,46 @@ +# Documentation + +Quick helps you verify how your Swift and Objective-C programs behave. +Doing so effectively isn't just a matter of knowing how to use Quick, +however. The guides in this directory can help you write +effective tests--not just using Quick, but even XCTest or other testing +frameworks. + +Each guide covers a particular topic. If you're completely new to unit +testing, consider reading them in the order they're introduced below: + +- **[Setting Up Tests in Your Xcode Project](SettingUpYourXcodeProject.md)**: + Read this if you're having trouble using your application code from within + your test files. +- **[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)**: + Read this to learn how to write `XCTestCase` tests that will help you write + code faster and more effectively. +- **[Don't Test Code, Instead Verify Behavior](BehavioralTesting.md)**: + Read this to learn what kinds of tests speed you up, and which ones will only end up + slowing you down. +- **[Clearer Tests Using Nimble Assertions](NimbleAssertions.md)**: + Read this to learn how to use Nimble to generate better failure messages. + Better failure messages help you move faster, by spending less time figuring out why + a test failed. +- **[Organized Tests with Quick Examples and Example Groups](QuickExamplesAndGroups.md)**: + Read this to learn how Quick can help you write even more effective tests, using + *examples* and *example groups*. +- **[Testing OS X and iOS Applications](TestingApps.md)**: + Read this to learn more about testing code that uses the AppKit and UIKit frameworks. +- **[Testing with test doubles](TestUsingTestDoubles.md)**: + Read this to learn what test doubles are and how to use them. +- **[Reducing Test Boilerplate with Shared Assertions](SharedExamples.md)**: + Read this to learn how to share sets of assertions among your tests. +- **[Configuring How Quick Behaves](ConfiguringQuick.md)**: + Read this to learn how you can change how Quick behaves when running your test suite. +- **[Using Quick in Objective-C](QuickInObjectiveC.md)**: + Read this if you experience trouble using Quick in Objective-C. +- **[Installing Quick](InstallingQuick.md)**: + Read this for instructions on how to add Quick to your project, using + Git submodules, CocoaPods, Carthage, or the Swift Package Manager. +- **[Installing Quick File Templates](InstallingFileTemplates.md)**: + Read this to learn how to install file templates that make writing Quick specs faster. +- **[More Resources](MoreResources.md)**: + A list of additional resources on OS X and iOS testing. +- **[Troubleshooting](Troubleshooting.md)**: + Read this when you experience other troubles. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..76e9d3e --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md @@ -0,0 +1,89 @@ +# Setting Up Tests in Your Xcode Project + +With the exception of the Command Line Tool project type, when you create a new project in Xcode 7, a unit test target is included +by default. [See specific instructions for a Command Line Tool Project](#setting-up-a-test-target-for-a-command-line-tool-project). To write unit tests, you'll need to be able to use your main +target's code from within your test target. + +## Testing Swift Code Using Swift + +In order to test code written in Swift, you'll need to do two things: + +1. Set "Defines Module" in your `.xcodeproj` to `YES`. + + * To do this in Xcode: Choose your project, then "Build Settings", then "Packaging" header, + then "Defines Module" line, then select "Yes". Note: you may have + to choose "All" (Build Settings) instead of "Basic" to see the + "Packaging" section. + +2. `@testable import YourAppModuleName` in your unit tests. This will expose Any `public` and `internal` (the default) + symbols to your tests. `private` symbols are still unavailable. + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Quick integration in the Xcode Test Navigator suffers from some limitations (open [issue](https://github.com/Quick/Quick/issues/219)). Quick tests will not show up in the navigator until they've been run, repeat runs tend to reset the list in unpredictable ways and the tests cannot be run from the gutter next to the source code. +> Please file a radar to Apple and mention this as a duplicate to [rdar://26152293](http://openradar.appspot.com/radar?id=4974047628623872) to promote this feature request for Apple Engineers. + +> Some developers advocate adding Swift source files to your test target. +However, this leads to [subtle, hard-to-diagnose +errors](https://github.com/Quick/Quick/issues/91), and is not +recommended. + +## Testing Objective-C Code Using Swift + +1. Add a bridging header to your test target. +2. In the bridging header, import the file containing the code you'd like to test. + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +You can now use the code from `MyClass.h` in your Swift test files. + +## Testing Swift Code Using Objective-C + +1. Bridge Swift classes and functions you'd like to test to Objective-C by + using the `@objc` attribute. +2. Import your module's Swift headers in your unit tests. + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Testing Objective-C Code Using Objective-C + +Import the file defining the code you'd like to test from within your test target: + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### Setting Up a Test Target for a Command Line Tool Project + +1. Add a target to your project in the project pane. +2. Select "OS X Unit Testing Bundle". +3. Edit the scheme of your main target. +4. Select the "Test" node, click the "+" under the "Info" heading, and select + your testing bundle. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md b/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md new file mode 100644 index 0000000..339bf34 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md @@ -0,0 +1,125 @@ +# Reducing Test Boilerplate with Shared Assertions + +In some cases, the same set of specifications apply to multiple objects. + +For example, consider a protocol called `Edible`. When a dolphin +eats something `Edible`, the dolphin becomes happy. `Mackerel` and +`Cod` are both edible. Quick allows you to easily test that a dolphin is +happy to eat either one. + +The example below defines a set of "shared examples" for "something edible", +and specifies that both mackerel and cod behave like "something edible": + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Shared examples can include any number of `it`, `context`, and +`describe` blocks. They save a *lot* of typing when running +the same tests against several different kinds of objects. + +In some cases, you won't need any additional context. In Swift, you can +simply use `sharedExamples` closures that take no parameters. This +might be useful when testing some sort of global state: + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> In Objective-C, you'll have to pass a block that takes a + `QCKDSLSharedExampleContext`, even if you don't plan on using that + argument. Sorry, but that's the way the cookie crumbles! + :cookie: :bomb: + +You can also "focus" shared examples using the `fitBehavesLike` function. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md b/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md new file mode 100644 index 0000000..fc4f3f9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md @@ -0,0 +1,129 @@ +# Testing with Mocks + +## Test doubles + +Dependencies between objects can cause problems when writing tests. For example, say you have a `Car` class that depends on/uses `Tire`. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests` tests `Car`, which calls `Tire`. Now bugs in `Tire` could cause `CarTests` to fail (even though `Car` is okay). It can be hard to answer the question: "What's broken?". + +To avoid this problem, you can use a stand-in object for `Tire` in `CarTests`. In this case, we'll create a stand-in object for `Tire` called `PerfectTire`. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` will have all of the same public functions and properties as `Tire`. However, the implementation of some or all of those functions and properties will differ. + +Objects like `PerfectTire` are called "test doubles". Test doubles are used as "stand-in objects" for testing the functionality of related objects in isolation. There are several kinds of test doubles: + +- Mock object: Used for receiving output from a test class. +- Stub object: Used for providing input to a test class. +- Fake object: Behaves similarly to the original class, but in a simplified way. + +Let's start with how to use mock objects. + +## Mock + +A mock object focuses on fully specifying the correct interaction with other objects and detecting when something goes awry. The mock object should know (in advance) the methods that should be called on it during the test and what values the mock object should return. + +Mock objects are great because you can: + +- Run tests a lot quicker. +- Run tests even if you're not connected to the Internet. +- Focus on testing classes in isolation from their dependencies. + +### Writing Tests with Mock Objects in Swift + +#### Sample app + +For example, let's create an app which retrieves data from the Internet: + +* Data from the Internet will be displayed in `ViewController`. +* A custom class will implement the `DataProviderProtocol`, which specifies methods for fetching data. + +`DataProviderProtocol` is defined as follows: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` gets data from the Internet and returns it using a `callback` closure. + +Here is the `DataProvider` class, which conforms to the `DataProviderProtocol` protocol. + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = URL(string: "http://example.com/")! + let session = URLSession(configuration: .default) + let task = session.dataTask(with: url) { + (data, resp, err) in + let string = String(data: data!, encoding: .utf8) + callback(data: string) + } + task.resume() + } +} +``` + +In our scenario, `fetch()` is called in the `viewDidLoad()` method of `ViewController`. + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### Testing using a Mock of `DataProviderProtocol` + +`ViewController` depends on `DataProviderProtocol`. In order to test the view controller in isolation, you can create a mock object which conforms to `DataProviderProtocol`. + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +The `fetchCalled` property is set to `true` when `fetch()` is called, so that the test can confirm that it was called. + +The following test verifies that when `ViewController` is loaded, the view controller calls `dataProvider.fetch()`. + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvider = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvider = mockProvider + + expect(mockProvider.fetchCalled).to(beFalse()) + + let _ = viewController.view + + expect(mockProvider.fetchCalled).to(beTrue()) + } + } +} +``` + +If you're interested in learning more about writing tests, continue on to . diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md b/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md new file mode 100644 index 0000000..375cb5a --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md @@ -0,0 +1,254 @@ +# Testing OS X and iOS Applications + +*[Setting Up Tests in Your Xcode Project](SettingUpYourXcodeProject.md)* +covers everything you need to know to test any Objective-C or Swift function or class. +In this section, we'll go over a few additional hints for testing +classes like `UIViewController` subclasses. + +> You can see a short lightning talk covering most of these topics + [here](https://vimeo.com/115671189#t=37m50s) (the talk begins at 37'50"). + +## Triggering `UIViewController` Lifecycle Events + +Normally, UIKit triggers lifecycle events for your view controller as it's +presented within the app. When testing a `UIViewController`, however, you'll +need to trigger these yourself. You can do so in one of three ways: + +1. Accessing `UIViewController.view`, which triggers things like `UIViewController.viewDidLoad()`. +2. Use `UIViewController.beginAppearanceTransition()` to trigger most lifecycle events. +3. Directly calling methods like `UIViewController.viewDidLoad()` or `UIViewController.viewWillAppear()`. + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## Initializing View Controllers Defined in Storyboards + +To initialize view controllers defined in a storyboard, you'll need to assign +a **Storyboard ID** to the view controller: + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +Once you've done so, you can instantiate the view controller from within your tests: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## Triggering UIControl Events Like Button Taps + +Buttons and other UIKit classes inherit from `UIControl`, which defines methods +that allow us to send control events, like button taps, programmatically. +To test behavior that occurs when a button is tapped, you can write: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` + +## Waiting for Asynchronous Operations with XCTestExpectation + +Tests sometimes need to wait for apps to complete operations such as animations and network calls that run asynchronously, either on a background queue or on a separate turn of the main run loop. (Aside: note that in most cases, tests should stub network calls and not actually use the network.) + +The standard XCTest way of handling asynchronous operations is to use [expectations](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html#//apple_ref/doc/uid/TP40014132-CH4-SW6). Quick supports these, but be careful! **Do not use `self` to get an instance of `XCTest`**. This includes creating or waiting for XCTest expectations: + +```swift +it("makes a network call") { + // 🛑 WRONG: don’t use self.expectation in Quick + let expectation = self.expectation(description: "network call") + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in expectation.fulfill() + }.resume() + // 🛑 WRONG: don’t use self.waitForExpectations in Quick + self.waitForExpectations(timeout: 1) +} +``` + +Why is this bad? Because when Quick runs your `spec()` function, it runs it on a dummy instance of `XCTest`. The real `XCTest` does not appear until those `it` closures actually run. In your `it` closures, `self` captures that dummy instance. Using this dummy instance to work with expectations is broken in two ways: + +- It sometimes fails with a “Questionable API usage” or “API violation” error. +- Sometimes it _appears_ to work, but even then it bypasses XCTest’s checks for common mistakes such as forgetting to call `waitForExpectations()`. + +The solution is to use `QuickSpec.current`, which returns the currently executing instance of XCTest: + +```swift +// Swift + +it("makes a network call") { + let expectation = QuickSpec.current.expectation(description: "network call") + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in expectation.fulfill() + }.resume() + QuickSpec.current.waitForExpectations(timeout: 1) +} +``` + +```objc +// Objective-C + +it(@"makes a network call", ^{ + XCTestExpectation *expectation = [QuickSpec.current expectationWithDescription:@"network call"]; + NSURLSessionTask *task = [NSURLSession.sharedSession + dataTaskWithURL: [NSURL URLWithString:@"https://example.com"] + completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { + [expectation fulfill]; + }]; + [task resume]; + [QuickSpec.current waitForExpectationsWithTimeout:1 handler:NULL]; +}); +``` + +### Nimble Alternative + +Nimble’s `expect(…).toEventually(…)` can also help test asynchronous operations: + +```swift +it("makes a network call") { + var networkCallCompleted = false + URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { + _ in networkCallCompleted = true + }.resume() + expect(networkCallCompleted).toEventually(beTrue()) +} +``` + +This approach has several drawbacks: + +- It is not thread safe. You have to do your own synchronization if the condition you’re testing for isn’t fulfilled on the main thread. +- It provides no sanity checking for unwaited conditions. +- It can’t aggregate multiple expectations in a single wait. +- It is slower, because `fulfill` immediately triggers success whereas `toEventually()` polls for it. + +However, `toEventually()` can lead to simpler test code, and may be a better choice when these concerns do not apply. diff --git a/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md b/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md new file mode 100644 index 0000000..c39403c --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md @@ -0,0 +1,9 @@ +# Common Installation Issues + +Here are solutions to common issues that come up when using the framework. + +## No such module 'Quick' + +- If you have already run `pod install`, close and reopen the Xcode workspace. If this does not fix the issue, continue below. +- Delete the _entire_ `~/Library/Developer/Xcode/DerivedData` direction, which includes `ModuleCache`. +- Explicitly build (`Cmd+B`) the `Quick`, `Nimble`, and `Pods-ProjectNameTests` targets after enabled their schemes from the Manage Schemes dialog. \ No newline at end of file diff --git a/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md b/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md new file mode 100644 index 0000000..2f0a138 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md @@ -0,0 +1,212 @@ +# Effective Tests Using XCTest: Arrange, Act, and Assert + +XCTest や Quick に限らず、テストフレームワークを使用する際、このパターンに従うことで効率的なユニットテストを書くことができます。 + +1. Arrange(環境構築) +2. Act(実行) +3. Assert(動作確認) + +## パターンに従ってテストを書く + +例として Banana クラスを用意します。 + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +ここでは `Banana.peel()` のテストをしてみましょう。このメソッドの期待する振る舞いはこのようになります。 + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 簡潔なテスト名を用いる + +この `testPeel()` テストのおかげで `Banana.peel()` が正しく動作しない場合、すぐ気付くことができます。 +我々のアプリケーションコードを変更することで正しく動作しないケース(テストが失敗するケース)はしばしば起こります。 +テストが失敗する場合は下記どちらかのケースになります。 + +1. 間違えてアプリケーションコードを壊してしまっているため、直す必要がある +2. アプリケーションコードは期待したとおりに動いているが、もともと期待した機能が変わっているためテストコードを直す必要がある + +もしテストが失敗した場合、どちらのケースに当てはまる判断する必要が出てきます。そのためテスト名が分かりやすいことが重要になります。 + +良いテスト名とは、 + +1. 何をテストしているか明確であること +2. どのような時にテストがパスするか・失敗するか明確であること + +例に挙げた `testPeel()` は良いテスト名でしょうか?分かりやすくしてみましょう。 + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +新しいテスト名は、 + +1. 何をテストしているか明確である: `testPeel` は `Banana.peel()` メソッドをテストしてることを示す。 +2. どのような時にテストがパスするか明確である: `makesTheBananaEdible` はバナナが食べられるか(edible)どうかをテストしていることを示す。 + +## テスト時の条件 + +人々がバナナを欲しい時、`offer()` というメソッドを使います。 + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +私達のアプリケーションコードは2つのうちどちらかを実行します: + +1. 食べられる(すでに皮がむかれている)バナナを注文するか +2. まだ食べられない(すでに皮がむかれている)バナナを注文するか + +両方のケースをテストしてみましょう。 + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +私達のテスト名は'どのような条件でテストをパスするか'を明確に表しています。 +`whenTheBananaIsPeeled`, `offer()` のケースでは `offersTheBanana` となるべきです。またバナナの皮がむかれていない場合は? +ここでは両方共テストしています。 + +ここで大事なことはアプリケーションコード内の各`if`文に対してそれぞれ1つのテストを持っていることです。 +これはテストを書く際の重要なアプローチです。このアプローチでは全ての条件(if文)に関してテストされていることを保証します。 +テストのうちどれか1つがでも失敗するようになったらコードの見直しをする必要があります。テスト名が分かりやすいとすぐにチェックすべき箇所が分かります。 + +## `XCTestCase.setUp()`を用いて簡潔に環境構築をする + +`OfferTests` の2つのテストのどちらにも同じ"環境構築"のコードが入っています。 +どちらのテストでも banana を作っています。このコードは一箇所にまとめるべきです。なぜでしょう? + +1. そのままにしておく場合、もし `Banana` の生成方法が変わったら, 私たちは全てのテストを修正しないといけなくなります。 +2. テストコードが短くなり、テストの可読性が向上します。 + +Banana の生成方法を `XCTestCase.setUp()` の中に移しましょう。`XCTestCase.setUp()` は各テストの実行前に一度呼び出されます。 + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## 複数のテストにまたがって環境構築を共有する + +もし複数のテストにまたがって同じ環境構築のコードを使っている部分があれば、 test target 内に'ヘルパー関数'を定義しましょう。 + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 共通操作を定義するのに関数を使いましょう。関数は継承できず、状態を保持することができません。継承や状態を持たせる場合、テストの可読性が落ちてしまいます。 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md b/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md new file mode 100644 index 0000000..af78e50 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md @@ -0,0 +1,81 @@ +# コードをテストせず、動作を確認する + +テストはアプリケーションが**期待と異なる動作** をした時のみ失敗するようにすべきです。 +アプリケーションコードが *何を* したかをテストすべきで、*どのように* したかをテストすべきではありません。 + +- アプリケーションが *何を* したかを確認するテストは **動作テスト(behavioral tests)** といいます。 +- アプリケーションの動作が変わっていなくても、コードを変更すると失敗するようになるテストは **脆弱なテスト(brittle tests)** といいます。 + +ここで `GorillaDB` というバナナのデータベースを用意します。 +`GorillaDB`は Key-Value 型のデータベースでバナナを保存することができます。 + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +そしてバナナをディスクから取り出すことができます。 + +```swift +let banana = database.load(key: "my-banana") +``` + +## 脆弱なテスト(Brittle Tests) + +どのようにして動作をテストするのでしょう?一つの方法としてここではバナナを保存した後にバナナのデータベースのサイズをチェックします。 + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + +ここで `GorillaDB` のソースコードを変更したとします。データベースからの読み出しを速くするためにもっとも頻繁に使用するバナナをキャッシュに保持するようにします。 +`GorillaDB.size` はキャッシュのサイズに合わせて大きくなります。この場合ディスクに保存しなくなるため上記のテストは失敗します。 + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 動作テスト(Behavioral Tests) + +動作のテストの重要なポイントは アプリケーションコードに期待する動作を明確にすることです。 + +`testSave_savesTheBananaToTheDatabase` というテストで期待する動作は バナナをデータベースに "保存する" ことでしょうか? +"保存する"というのは 後から読み出すことができる、という意味です。そのためデータベースのサイズが大きくなることをテストするのではなく、 +バナナを読み出すことができるかをテストすべきです。 + + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +動作テストを書く際の重要なポイント: + +- アプリケーションコードが何をすべきか明確にしているか? +- テストが *動作のみ* をテストしているか?コードの動作が他の要因で意図しない動きにならないか。 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md b/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md new file mode 100644 index 0000000..3c2432f --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md @@ -0,0 +1,101 @@ +# Quickの挙動をカスタマイズしましょう + +`QuickConfiguration` を継承したクラスを作成し、`QuickConfiguration.Type.configure()` をオーバーライドすることで Quick の挙動をカスタマイズすることができます。 + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +一つのプロジェクトで複数の configuration を持つこともできますが +どの順に configuration が実行されるか保証されません。 + +## テスト全体で使う `beforeEach` と `afterEach` を追加する + +`QuickConfiguration.beforeEach` と `QuickConfiguration.afterEach` を使うと +テストスイート内の各テストの実行前・実行後に走らせる処理を記述することができます。 + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +さらに現在実行中のテストに関するメタデータを取得することもできます。 + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md b/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md new file mode 100644 index 0000000..1c87e52 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md @@ -0,0 +1,26 @@ +# Quickファイル・テンプレートのインストール方法 + +Quick のリポジトリには Swift, Objective-C の両方で使用できるテンプレートが含まれています。 + +## Alcatraz + +Quick のテンプレートは Xcode のパッケージマネージャーの [Alcatraz](https://github.com/supermarin/Alcatraz) 経由でインストールできます。 +パッケージマネージャーから検索してみてください。 + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Rakefile から手動でインストールする + +手動でインストールすることもできます。 +リポジトリを clone して rake task の `templates:install` を実行してください。 + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +アンインストールも簡単です、下記コマンドを実行してください。 + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md b/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md new file mode 100644 index 0000000..884b8a5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md @@ -0,0 +1,152 @@ +# Quickのインストール方法 + +> **もし Xcode 7.1 を使用していたら** 現時点で最新バージョンの Quick--`v0.9.0` を使用してください +> 最新のリリースは `swift-2.0` branch で開発されています。 + +Quick は examples(テスト) and example groups(テストグループ)の文法を提供します。 +Nimble は `expect(...).to` の文法を提供します。 +テストでは両方を使ってもいいですし、どちらか片方を使う、ということもできます。 + +Quick をテストに組み込むには3つの方法があります。 + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) + +下記のインストール手順の中からどれか選択してインストールを進めてください。 +インストール完了後、テストターゲット内のファイルで Quick を使用(`import Quick`)できるようになります。 + +## Git Submodules + +Git submodules を使って Quick と Nimble をリンクします。手順の流れとしては下記の通りです。 + +1. Quick を submodule として追加. +2. プロジェクトで`.xcworkspace`を使っていなければ作成してください。 ([こちらを参照](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. `Quick.xcodeproj` をプロジェクトの`.xcworkspace`に追加してください。 +4. `Nimble.xcodeproj` をプロジェクトの`.xcworkspace`に追加してください。 `Nimble.xcodeproj` は `path/to/Quick/Externals/Nimble` にあります。 Quick が依存している Niimble を追加することで Quick のバージョンと Nimble のバージョンを合わせられます。 + +5. `Quick.framework` と `Nimble.framework` を BuildPhase の "Link Binary with Libraries" でリンクします。 + +もしまだ git submodules 用のディレクトリを作っていなかったら、まず始めにディレクトリを作成します。 +`Vendor` という名前のディレクトリを用意しましょう。 + +**Step 1:** Quick と Nimble を Git submodules としてダウンロードする + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step 2:** `Quick.xcodeproj` と `Nimble.xcodeproj` をプロジェクトの `.xcworkspace` に追加してください。 +例として `Guanaco.xcworkspace` という workspace に Quick と Nimble を追加します。 + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step 3:** build phase の `Link Binary with Libraries` に `Quick.framework` を追加してください。 +2種類の `Quick.frameworks` が表示されますが 1 つは OS X 用で、もう 1 つが iOS 用です。 + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +`Nimble.framework` も同様に追加してください。これで完了です! + +**Submodules をアップデートする:** Quick と Nimble を最新バージョンにアップデートしたい場合は Quick ディレクトリに入って master リポジトリから pull してください。 + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +あなたのプロジェクトの Git リポジトリは submodule の変更もトラッキングしているので Quick submodules の更新を commit しておきます。 + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Quick Submodule を含んだ リポジトリを git clone する:** 他の開発者があなたのリポジトリを clone したあと、submodules を同様に pull してくる必要があります。`git submodule update` コマンドを実行することで pull できます。 + +```sh +git submodule update --init --recursive +``` + +git submodules に詳細な情報は[こちら](http://git-scm.com/book/en/Git-Tools-Submodules)です。 + +## CocoaPods + +CocoaPods でインストールする場合、バージョンは 0.36.0 以降である必要(CocoaPods が Swift をサポートしているバージョン)があります。 + +Podfile に Quick と Nimble を追加して下さい。 Swift では ```use_frameworks!``` も必要です。 + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick', '~> 0.9.0' + pod 'Nimble', '3.0.0' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +その後 pod install でダウンロード、リンクします。 + +```sh +pod install +``` + +### Swift 1.2 で使う + +Quick の最新版(0.4.0)は Swift 2 (Xcode 7) 用ですが、Nimble の最新版(1.0.0) は Swift 1.2 (Xcode 6) 用です。 + +もし Xcode6 で使いたい場合は下記のようにバージョン指定してください。 + +```sh +target 'MyTests' do + use_frameworks! + pod 'Quick', '~>0.3.0' + pod 'Nimble', '~>1.0.0' +end +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +テストターゲットは "Embedded Binaries" section がないので framework はターゲットの "Link Binary With Libraries" に追加する必要があります。 build phase の "Copy Files" も同様にターゲットの framework destination を指定して下さい。 + + > Carthage は dynamic frameworks をビルドするので code signing identity に有効なものを設定しておく必要があります。 + +1. Quick を [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) に追加してください。 + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. `carthage update` を実行してください。 +3. `Carthage/Build/[platform]/` ディレクトリから Quick と Nimble をテストターゲットの "Link Binary With Libraries" に追加してください。 + ![](http://i.imgur.com/pBkDDk5.png) + +4. テストターゲットの build phase で "New Copy Files Phase" を選択してください。 + ![](http://i.imgur.com/jZATIjQ.png) + +5. "Destination" を "Frameworks" に設定して、2つの framework を追加してください。 + ![](http://i.imgur.com/rpnyWGH.png) + +Carthage の dependency の管理方法はこの方法だけではありません。 +詳細な情報はこちらを参照してください [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md) 。 + +### (非推奨) 実機で Quick のテストを走らせる + +Quick で書かれたテストを実機で走らせるためには `Quick.framework` と `Nimble.framework` を `Embedded Binaries` としてテストターゲットの `ホストアプリケーション` に追加されます。 Embedded binary として framework を追加すると Xcode が自動的にホストアプリケーションにリンクしてしまいます。 + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md b/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md new file mode 100644 index 0000000..996f2df --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md @@ -0,0 +1,27 @@ +# その他の参考資料 + +## Quick のテストのサンプル + +Quick は[GitHub](https://github.com/github)や[ReactiveCocoa](https://github.com/ReactiveCocoa)を含む多くの企業、OSS プロジェクト、個人で利用されています。 + +下記リポジトリを参考にしてみてください。 + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/Moya/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## OS X と iOS Apps のテストに関する参考資料 + +- **[Quality Coding](http://qualitycoding.org/)**: + ユニットテストにフォーカスした iOS 開発に関するブログ。 +- **[OCMock Tutorials](http://ocmock.org/support/)**: + テストでモックが必要な時に使用する OCMock のチュートリアル。 +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**: + 通信を行うコードをテストする時はこのライブラリを使用して下さい。 +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + Nimble の matcher の書き方に関するドキュメントはこちら([the Nimble documentation](https://github.com/Quick/Nimble)) diff --git a/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md b/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md new file mode 100644 index 0000000..429d6a4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md @@ -0,0 +1,100 @@ +# Nimble Assertions を使ってテストをより簡潔に + +テストが期待した通りに動作しない時、ユニットテストは **何が問題か** を明確にすべきです。 + +次の関数はサルの集団から馬鹿なサルだけを取得します。 + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +ここでこの関数に対するテストを書いてみましょう。 + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +このテストは下記のメッセージとともに失敗します。 + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +失敗した時は多くの情報を残すことが望ましいです。このメッセージのままではよく分かりません。 +true や false だけではそれがなにか分かりません。このままではテストコードから原因を見つけるまでに時間がかかってしまいます。 + +## 良い失敗メッセージを残す: Part 1: XCTAssert に手動でメッセージを渡す + +`XCTAssert` は失敗時にメッセージを指定することができます。 + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +しかし`XCTAssert`では自分でメッセージを指定しないといけません。 + +## 良い失敗メッセージを残す: Part 2: Nimble Failure Messages を使う + +Nimble は Assert, 失敗時のメッセージを読みやすくしてくれます。 + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +Nimble では自分でメッセージを指定しなくても Nimble がとても読みやすいメッセージを返してくれます。 + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: verySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +失敗メッセージは何が問題かを明確にします:ここでは `kiki` が `silliest()` の戻り値に含まれることを期待していますが +このテストでは `jane` しか含まれていません。Nimble からのメッセージで何が問題かが分かりやすく伝えられるので、簡単に直すことができます。 + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble は具体的な失敗メッセージを返してくれる多くの種類の Assertion を提供します。 +`XCTAssert` と違って毎回自分でメッセージを指定することはありません。 + +Nimble の全ての assertion はこちらで確認できます: [Nimble README](https://github.com/Quick/Nimble) 。 +下記に幾つかの例を示します。 + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md b/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md new file mode 100644 index 0000000..9b1d161 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md @@ -0,0 +1,477 @@ +# QuickのExamplesとExample Groupsで、たくさんのテストでも整理整頓 + +Quick では **examples** と **example groups** という特別な文法があります。 + +*[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)* では, +良いテスト名をつけることがとても重要だということを学びました。 +テストが失敗した時、テスト名はアプリケーションコードを直すべきかテストを修正すべきかを判断する際の重要な材料になります。 + +Quick の examples(テスト) と example groups(テストグループ) は二つの役に立ちます。 + +1. 記述的なテスト名を書くためことをサポートします +2. テスト中の "環境構築" 部分におけるコードを簡略化します + +## Examples の `it` + +Examples は `it` という「コードがどのように動作すべきかを宣言する」関数を持ちます。 +これは XCTest の test methods のようなものです。 + +`it` 関数は2つのパラメータ、example の名前と closure です。 +下記のテストでは `Sea.Dolphin` クラスがどのように動作すべきかを記述しています。 +この example では「新しく生成された Dolphin は smart で friendly であるべき」と書いています。 + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +Examples が何をテストしているかを明確にするために Description を使います。 +Description は文字数制限がなくどの文字でも(絵文字さえも!)使うことができます。 +:v: :sunglasses: + +## Example Groups の `describe` と `context` + +Example groups では Example のグルーピングができ、 setup と teardown のコードを共有できます。 + +### `describe` を使ってクラスと関数について記述する + +`Dolphin` クラスの `click` 関数の動作を記述する際に、 +言い換えると関数が動作していることをテストする際に、 +複数の `it` example を `describe` を用いてグルーピングすることができます。 +似ている examples をまとめることで可読性が向上します。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +Xcode でこれらの examples を実行すると`describe` と `it` の記述内容も表示されます。上記のテストの場合、下記のような出力になります。 + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +それぞれの Example が何をテストしているかが明確ですね。 + +### `beforeEach` と `afterEach` を使って Setup/Teardown のコードを共有する + +Example groups はテストの内容をただ分かりやすくするだけでなく同一グループ内のsetup/teardownコードを共有することができます。 + +下記の例では`its click`の Example group のテストを実行する前に `beforeEach`を使って新しい Dolphin のインスタンスを生成しています。 +各 Example において "新しい" 状態でテストが行えます。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +この例では setup を共有することはあまりメリットがないように見えるかもしれませんが +複数の複雑なオブジェクトを生成する時などコード量を節約することができます。 + +それぞれの Example を実行した後に実行したいコードについては`afterEach`を使います。 + +### `context` を使ってある条件での動作を記述する + +例の Dolphins(イルカ達) はエコーロケーションのために カチッと音を立てます(`click` 関数を呼び出します)。 +イルカ達は特に興味のあるものに近づく時、それが何かを調べるために連続してエコーロケーション(`click` 関数を呼び出します)を行います。 + +このシナリオにおいてテストが 異なる状況において `click` 関数の動作は異なる ということを表す必要があります。 + +基本的にイルカは一度音を鳴らすだけですが、イルカ達が興味があるものが近くにあると連続して音を鳴らします。 + +この状況について `context` 関数を使って表します。ある `context` では通常のケースで、もう一方の`context`ではイルカが興味あるものに近づいているケースです。 + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +厳密には `context` キーワードは `describe`と同じですがテストを理解しやすくなるので使い分けるとよいです。 + +### テストの可読性: Quick と XCTest + +*[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)*で各条件についてそれぞれテストを用意するのがテストを書く際の重要な方法と述べましたが +このアプローチで XCTest でテストを書くとテスト名が長くなってしまいます。 + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Quick を使うと条件について読みやすく、しかもそれぞれの Example group について環境構築が効率的に行えます。 + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 一時的に Examples や Example Groups を無効にする + +通っていない Example を一時的に無効にすることもできます。 +Example や Example Groups の先頭に `x` をつけると無効になります。 +Examples の名前がテスト結果の中に出力されますがテストは実行されなくなります。 + + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 指定した Examples だけ一時的に実行する + +一部の Example だけ実行できると便利なこともあります。 +そのような時は実行したい Example を `fit` 関数を用いて指定します。 +特定の Example group だけ実行したい時は`fdescribe` か `fcontext` を記述します。 +※もともと書いてあるテストコードの先頭に `f` を追記するだけです。 + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## `beforeSuite` と `afterSuite` を使ってテスト全体に対する Setup/Teardown を行う + +テストの環境構築の中にはどの Example よりも先に、または最後に実行したいものがある場合もあります。 +このような時は `beforeSuite` か `afterSuite` を使います。 + +下記の例では 全ての Example が実行される前に一度だけ海の全ての生物のデータベースが生成され、全ての Exmample が実行された後にデータベースを削除しています。 + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +`beforeSuite` and `afterSuite` は必要な数だけ定義することができます。 +全ての `beforeSuite` の closure は全てのテストが実行される前に実行され、 +全ての `afterSuite` の closure は全てのテストが実行された後に実行されます。 + +複数の `beforeSuite`(`afterSuite`) の closure を記述した場合、これらの実行順序は記述した順序で実行されるかは保証されません。 + +## 実行中の Example でメタデータにアクセスする + +実行中の Example の中で、Example名を知りたいケース、これまでに何件の Example を実行したかを知りたいケースがあるかもしれません。 +Quick ではこれらの情報に `beforeEach` と `afterEach` の closure の中からアクセスすることができます。 + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md b/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md new file mode 100644 index 0000000..6d67044 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md @@ -0,0 +1,48 @@ +# Objective-C で Quick を使う + +Quick は Swift でも Objective-C でも問題なく動作します。 + +ですが、Objective-C で Quick を使う場合、2点気を付けておきべきことがあります。 + +## 簡略記法 + +Objective-C で Quick を import すると `it` と `itShouldBehaveLike` というマクロが定義されます。 +また、`context()` and `describe()`といった関数も同様に定義されます。 + +もしプロジェクトですでに同じ名前のシンボルを定義していた場合、重複のためビルドエラーになります。 +その場合は下記のように`QUICK_DISABLE_SHORT_SYNTAX`を定義してこの機能を無効にしてください。 + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +`QUICK_DISABLE_SHORT_SYNTAX`マクロは Quick ヘッダを import する前に定義する必要があります。 + + +## Swift のファイルを テストターゲットに含める + +テストターゲットの中に Swift のファイルが含まれていないと Swift stlib が リンクされないため Quick が正しく実行されません。 + +Swift のファイルが含まれていないと下記のようなエラーが発生します。 + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +修正するためには `SwiftSpec.swift` という名前の空のファイルをテストターゲットに追加してください。 + +```swift +// SwiftSpec.swift + +import Quick +``` + +> この問題に関する詳細情報はこちら https://github.com/Quick/Quick/issues/164. diff --git a/Carthage/Checkouts/Quick/Documentation/ja/README.md b/Carthage/Checkouts/Quick/Documentation/ja/README.md new file mode 100644 index 0000000..0c4f0d5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/README.md @@ -0,0 +1,50 @@ +# テストの書き方、Quickの使い方 + +Quickでテストを書くと、SwiftとObjective-Cで書かれたプログラムがどう動作しているか楽に確認できます。 + +ところが、有用なテストはQuickを使わなくても書けます。 +役に立つテストが書けるようになるには、Quickのようなフレームワークの使い方を覚える必要はありません。 + +このディレクトリにあるファイルは、QuickかXCTestかを問わず、 +「役に立つ」テストとは何か、そしてどうやってそういったテストが書けるか、 +それを拙文ながら説明しようとしています。 + +目次: + +(テストについて事前知識がまったくない方は、順に読んでいくことをオススメします。) + +- **[Xcodeでテストを用意しましょう](SettingUpYourXcodeProject.md)**: + アプリのコードがテスト・ファイルから参照できない場合や、 + その他スムーズにテストが動かない場合はこのファイルを読み返すといいかもしれません。 +- **[XCTestで役に立つテストを書く方法:Arrange(環境構築), Act(実行), and Assert(動作確認)](ArrangeActAssert.md)**: + 役に立つテストを書くための基本中の基本。これさえ覚えれば、 + XCTestを使ってあなたも正確に動作するコードをすばやく書けるようになります。 +- **[コードをテストするのではなく、動作の確認をしましょう](BehavioralTesting.md)**: + 同じ「テスト」でも、開発を進めやすくするテストと、邪魔ばかりするテストとがあります。 + 見分ける方法は、このファイルを読めば分かります。 +- **[Nimbleのassertでテストをより読みやすくしましょう](NimbleAssertions.md)**: + Nimbleを使って、テストが失敗したときわかりやすいエラーメッセージを出すようにしましょう。 + わかりやすいメッセージで、テストがなぜ失敗したのかが一瞬でわかって開発の速度があがります。 +- **[QuickのExamplesとExample Groupsで、たくさんのテストでも整理整頓](QuickExamplesAndGroups.md)**: + Quickを使う大きなメリットのひとつはexamplesとexample groupsです。 + これでより簡潔にたくさんのテストが書けるようになります。 +- **[OS XとiOSアプリのテスト](TestingApps.md)**: + AppKitとUIKitを使ったコードをどうやってテストできるか説明します。 +- **[Test doublesを使ったテスト](TestUsingTestDoubles.md)**: + Test doublesを使って対象のクラスのみをテストする方法を説明します。 +- **[assertの共有でボイラープレートコードをなくしましょう](SharedExamples.md)**: + どうやってassertを共有できるか、なぜそうするのが望ましいのか説明します。 +- **[Quickの挙動をカスタマイズしましょう](ConfiguringQuick.md)**: + Quickがテストを実行するときの挙動をどうやって変えられるか説明します。 +- **[Objective-CでQuickを使う方法・注意点](QuickInObjectiveC.md)**: + QuickをObjective-Cで使ったときに思わぬ不具合・トラブルがあった場合、 + これを読んでください。 +- **[Quickのインストール方法](InstallingQuick.md)**: + あなたのプロジェクトにQuickを導入する方法を説明します。Git submodules、 + CocoaPods、Carthage、全部サポートしています! +- **[Quickファイル・テンプレートのインストール方法](InstallingFileTemplates.md)**: + Quickテストをすばやく作成するためのファイル・テンプレートをインストールする方法を説明します。 +- **[その他の参考資料](MoreResources.md)**: + OS X・iOSのテストに関しての資料集を用意しています。 +- **[トラブルシューティング](Troubleshooting.md)**: + その他の不具合に遭遇した場合にこれを読んでください。 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..9258217 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md @@ -0,0 +1,77 @@ +# テストの準備をする + +Xcode7 では Command Line Tool プロジェクトを除き、デフォルトで Unit test target が生成されます。 [参照:コマンドラインツールプロジェクトでテストの準備をする](#コマンドラインツールプロジェクトでテストの準備をする)。 +テストを書くためには Unit test targetから Main target のコードが使用できる必要があります。 + +## Swift のコードを Swift でテストする + +Swift で書かれたコードをテストするためには下記2つの作業を行います。 + +1. プロジェクトファイル `.xcodeproj` の "defines module" を `YES` に設定します。 + + * Xcode で対象のプロジェクトを開き、"Build Settings" の "Defines Modules" の 項目を "Yes" にします。 + +2. 各テストファイルで `@testable import YourAppModuleName` を追記します。 追記することで public, internal のシンボルにアクセスできるようになります。`private` シンボルはアクセスできないままです。 + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Swift のファイルを Test target に含める、という方法もありますが、不具合を引き起こす([subtle, hard-to-diagnose +errors](https://github.com/Quick/Quick/issues/91)) ことがあるためお勧めしません。 + +## Objective-C のコードを Swift でテストする + +1. Bridging header を test target に追加します。 +2. Bridging header 内で テストしたいコードを import します。 + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +これで `MyClass.h` のコードを Swift のテストコードから使用できるようになります。 + +## Swift のコードを Objective-C でテストする + +1. テストしたい Swift のクラスと関数に`@objc`属性を付加します。 +2. テストコードで Module の Swift header を import します。 + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Objective-C のコードを Objective-C でテストする + +テストコード内でテスト対象を import します。 + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### コマンドラインツールプロジェクトでテストの準備をする + +1. プロジェクトのペインからターゲットを追加(+ボタンを押下) +2. "OS X Unit Testing Bundle" または "iOS Unit Testing Bundle" を選択 +3. Main target で "Edit the scheme" を選択 +4. "Test" を選択, "Info" タブで "+" をクリックして追加した testing bundle を選択 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md b/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md new file mode 100644 index 0000000..a1670d2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md @@ -0,0 +1,122 @@ +# assertの共有でボイラープレートコードをなくしましょう + +複数のオブジェクトに対象して同じ内容のテストを行いたい場合があります。 + +例えば `Edible` という protocol があるとします。 +イルカ(dolphin)が何か食べられる(`Edible`な)ものを食べるとイルカが幸せになります。 +サバ(`Mackerel`)とタラ(`Cod`)は食べられる(`Edible`な)ものです。 + +Quick は「イルカがどちらかを食べて幸せになる」ということを簡単にテストすることできます。 + +下記で示すテストは "(何かを食べる)something edible" という共有できるテスト(Shared examples)を定義しています。 +また、この共有できるテストでサバ(Mackerel)とタラ(Cod)を食べることについてのテストを記述しています。 + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Shared examples は `it`, `context` や `describe` のブロックをいくつでも含めることができます。 +これは異なる種類の対象についてテストをする際のコードを節約することができます。 + +あるケースでは context を追加する必要もありません。 +Swift では `sharedExamples` closure を使って共有できるテストを定義することができます。 +このテクニックはある時点での状態をテストしたい時などに役に立つかもしれません。 + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Objective-Cでは, `QCKDSLSharedExampleContext` を引数に取る block を渡すことができます。※QCKDSLSharedExampleContext を使う予定がなくても引数に取る block を用意してください。めんどくさくても。世の中そんなもんです。 :cookie: :bomb: + +`itBehavesLike` の先頭に `f` を加えて(`fitBehavesLike`) として共有できるテストのみ実行することもできます。 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md b/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md new file mode 100644 index 0000000..7251e2e --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md @@ -0,0 +1,138 @@ +# Test doubles を使ったテスト + +## Test doubles + +テストを書いているとしばしば次のような問題にぶつかります。 `車`クラスが`タイヤ`クラスを使用している(依存している)とします。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +ここで 車Tests という (`タイヤ`に依存している)`車` のテストを用意します。ここで `タイヤ` にバグがあった場合、`車`に問題なくても 車Tests は失敗します。 +このような事が頻繁に起こるとバグの究明が難しくなります。 + +この問題を回避するには、`車`Tests において `タイヤ`の 代わりになるクラス`完璧タイヤ` クラス(代理、英語で `Stand-in`といいます)を用意する、という方法があります。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +この`完璧タイヤ`は実装は異なりますが`タイヤ`と同じメソッド、プロパティを持ちます。そのため 車Tests において `タイヤ` を `完璧タイヤ` と入れ替えることができます。 + +`完璧タイヤ`クラスのような差し替え可能なオブジェクトのことを一般に'test doubles(テストダブル)'と呼びます。 +'test doubles' にはいくつか種類があります。 + +- Mock object: テスト対象のクラスの出力の検証に用いる +- Stub object: テスト対象のクラスにデータを渡す(入力)際に用いる +- Fake object: 差し替え前のオブジェクトと近い振る舞いをする(実装がより簡単になっている) + +ここではモックを使ったテストの方法を紹介します。 + +## モックとは + +モックとはテスト対象のオブジェクト(クラス、構造体)が呼び出し先のオブジェクトと意図したとおりに協調動作するかどうかをテストするために使うオブジェクトのことです。 + +## Swift でモックを使ったテストを書く + +### サンプルアプリケーション + +ここでは例としてインターネット経由で取得したデータを表示するアプリケーションを考えます。 + +* DataProviderProtocolというプロトコルを実装したクラスがインターネット経由でデータを取得する +* 取得したデータをViewControllerで表示する + +ここで DataProviderProtocol を定義します。 + +```swift +// Swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +DataProviderProtocol の `fetch()`関数でデータを取得し、callbackブロックでデータを渡します。 + +ここで DataProviderProtocol を実装する DataProvider クラスを定義します。 + +```swift +// Swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = NSURL(string: "http://example.com/")! + let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) + let task = session.dataTaskWithURL(url, completionHandler: { + (data, resp, err) in + let string = NSString(data:data!, encoding:NSUTF8StringEncoding) as! String + callback(data: string) + }) + task.resume() + } +} +``` + +ViewController の `viewDidLoad` 中にデータの取得(`fetch()`の呼び出し)を行います。 + +コードはこのようになります。 + +```swift +// Swift +class ViewController: UIViewController { + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +## DataProviderProtocol のモックを使ったテストを書く + +この例では ViewController は DataProviderProtocol に依存しています。 +テスト用に DataProviderProtocol を継承したクラス(モックとして使用します)をテストターゲット内に作成します。 + +モックを作成することで、 +- テストを速く実行できる +- インターネットに接続していなくてもテストができるようになる +- ViewController の動作のテストにフォーカスできる(実際のDataProviderをテスト対象から外すことが出来る) + +```swift +// Swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +このモックの中で fetchCalled プロパティを定義しています。 fetchCalled は fetch 関数が呼ばれたら true になります。 +これで準備は完了です。 + +このモックを使ってテストをします。このテストで「 ViewController がロードされた時(viewDidLoad)に dataProvider を使って fetch() を実行するか」という動作をテストしています。 + +```swift +// Swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvier = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvier = mockProvier + + expect(mockProvier.fetchCalled).to(equal(false)) + + let _ = viewController.view + + expect(mockProvier.fetchCalled).to(equal(true)) + } + } +} +``` + +このようにオブジェクトのモックを作ることで動作をテストしやすくなります。 + +テストの書き方について、更に詳細を知りたい方はこちらのビデオを参考にしてください。 https://realm.io/jp/news/testing-in-swift/ 。 diff --git a/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md b/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md new file mode 100644 index 0000000..db389ee --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md @@ -0,0 +1,174 @@ +# Testing OS X and iOS Applications + +*[Xcodeでテストを用意しましょう](SettingUpYourXcodeProject.md)*では Objective-C や Swift の関数やクラスを +テストするために必要なことを述べました。ここでは `UIViewController` のサブクラスなどをテストする際のポイントを述べます。 + +> 関連する LT がありますので[こちら](https://vimeo.com/115671189#t=37m50s)も参考にしてください。 (37'50" から始まる部分です)。 + +## `UIViewController` のライフサイクルイベントを発火させる + +通常は UIKit が view controller のライフサイクルイベントを発火しますが、 +テストをする時は自分たちでライフサイクルイベントを発火させる必要があります。 +呼び出すには3つの方法があります。 + +1. `UIViewController.view`にアクセスする、すると `UIViewController.viewDidLoad()` のイベントが発火します。 +2. `UIViewController.beginAppearanceTransition()` を呼び出すとほとんどのライフサイクルイベントが発火します。。 +3. `UIViewController.viewDidLoad()` や `UIViewController.viewWillAppear()` などのライフサイクルに関わる関数を直接呼び出す。 + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## Storyboard 内に定義した View Controller を初期化する + +Storyboard 内に定義した View Controller を初期化する際は **Storyboard ID** を定義しておく必要があります。 + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +**Storyboard ID** を定義しておくとテストコードから ViewController を初期化することができます。 + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## ボタンをタップされた、などの UIControl Events を発火させる + +ボタンや他の `UIControl` を継承したクラスは Control イベントを発火させる関数を持っています。 +ボタンをタップされた時の動作をテストするにはこのように書くことができます: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md b/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md new file mode 100644 index 0000000..095dad3 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md @@ -0,0 +1,9 @@ +# トラブルシューティング + +Quick を使用するときによくぶつかる問題の解決策を紹介します。 + +## Cocoapods でインストールした時に「No such module 'Quick'」エラーが出る + +- すでに `pod install` を実行していた場合、一度 Xcode workspace を閉じて再度開いてみてください。それでも解決しない場合は次の手順を試してみてください。 +- `ModuleCache` を含む `~/Library/Developer/Xcode/DerivedData` をすべて削除してください。 +- `Manage Schemes`ダイアログから`Quick`、`Nimble`、`Pods-ProjectNameTests` ターゲットの Scheme が有効なことを確認して、明示的にビルド(`Cmd+B`)をやり直してみてください。 diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md new file mode 100644 index 0000000..e60967d --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/ArrangeActAssert.md @@ -0,0 +1,203 @@ +# XCTest를 사용한 효과적인 테스트 : Arrange, Act, 그리고 Assert + +XCTest, Quick, 또는 다른 테스트 프레임워크를 사용하는 경우, 간단한 패턴을 따라 효과적인 단위 테스트를 작성할 수 있습니다: + +1. Arrange (환경 구축) +2. Act (실행) +3. Assert (동작 확인) + +## Arrange, Act, and Assert 사용하기 + +예를 들어, `Banana`라는 클래스를 간단히 살펴봅시다: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + + `Banana.peel()` 메서드가 어떻게 되는지 확인해 봅시다: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 간단한 테스트 이름 사용하기 + +이 `testPeel()` 테스트 덕분에 `Banana.peel()` 메소드가 제대로 작동하지 않는다면 즉시 알 수 있습니다. 이는 일반적으로 응용 프로그램 코드가 변경되면서 발생합니다. + +1. 우리는 뜻하지 않게 응용 프로그램 코드를 망가트리므로, 응용 프로그램 코드를 수정해야 합니다. +2. 우리는 응용 프로그램의 작동 방식을 변경했습니다. — 아마도 새로운 기능을 추가했기 때문일 수 있습니다. — 그래서 우리는 테스트 코드를 변경해야 합니다. + +만약 테스트가 실패하기 시작한다면, 위 두 가지 중 어떤 케이스인지 어떻게 알 수 있을까요? 따라서 **테스트의 이름**을 알기 쉬운 것이 중요하다는 사실을 알려줍니다. 좋은 테스트 이름들 : + +1. 무엇을 테스트하고 있는지 명확합니다. +2. 어떤 때 테스트가 통과하거나 실패하는지 명확합니다. + + `testPeel()` 메소드는 좋은 테스트 이름일까요? 더 명확하게 바꾸어 봅시다: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +새로운 이름: + +1. 무엇을 테스트하고 있는지 명확합니다 : `testPeel` 은 `Banana.peel()` 메소드 임을 나타냅니다. +2. 어떤 때 테스트가 통과하거나 실패하는지 명확합니다 : `makesTheBananaEdible` 는 메소드가 호출되면 바나나가 식용 가능한 상태임을 나타냅니다. + +## 테스트 시 조건들 + +`offer()` 함수를 사용해서 사람들에게 바나나를 제공하고 싶다고 가정해 보겠습니다 : + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +우리의 프로그램 코드는 다음 두 가지 중 하나를 수행합니다 : + +1. 이미 벗겨진(먹을 수 있는) 바나나를 제공합니다… +2. …또는 벗겨지지 않은(먹을 수 없는) 바나나를 제공합니다. + +이 두 가지 경우에 대한 테스트를 작성해 봅시다 : + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +테스트 이름은 테스트가 통과해야 하는 **조건**을 명확하게 나타내야 합니다 : 예를 들면 `whenTheBananaIsPeeled`, `offer()` 은 `offersTheBanana` 가 되어야 합니다. 만약 바나나가 벗겨지지 않은 경우라도 우리는 역시 이 경우를 테스트했습니다! + +코드에서 `if` 문 하나에 테스트가 하나씩 가지고 있는 것을 주목해 봅시다. 이것은 테스트를 작성할 때 훌륭한 패턴입니다 : 이 패턴은 모든 조건이 테스트 되는 것을 보장합니다. 이러한 조건 중 하나가 더 이상 작동하지 않거나 변경이 필요 없게 된다면, 우리는 어떤 검사가 필요한지 정확히 알 수 있게 됩니다. + +## `XCTestCase.setUp()` 을 사용하여 간단히 환경구축 하기 + +`OfferTests` 에는 같은 "환경 구축" 코드가 포함되어 있습니다 : 이들은 둘 다 바나나를 만듭니다. 우리는 이 코드를 한 곳에 정리해야 합니다. 왜일까요? + +1. 그대로 두었을 때 `바나나` 생성 방식이 변경되면, 모든 바나나를 만드는 테스트들을 수정해야 합니다. +2. 테스트 코드가 짧아지고 (그리고 **그렇게 만드는 경우에만** ) 테스트의 가독성이 향상됩니다. + +`바나나` 초기화 코드를 모든 테스트 메소드 전에 한 번 실행되는 `XCTestCase.setUp()` 안으로 옮기세요. + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## "환경구축" 코드를 여러 테스트에서 공유하기 + +여러 테스트 간에 동일한 "환경구축" 코드를 사용하는 부분을 발견하면, test target에 'helper 함수'를 정의합시다 : + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 함수를 사용하여 헬퍼를 정의하십시오 : 함수는 서브클래스화 할 수 없으며, 어떤 상태도 유지할 수 없습니다. 서브 클래스화 및 변경 가능한 상태는 당신의 테스트를 읽기 힘들게 합니다. diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md new file mode 100644 index 0000000..39dd525 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/BehavioralTesting.md @@ -0,0 +1,80 @@ +# 코드를 테스트하지 말고, 동작을 확인하라 + +테스트는 응용프로그램이 **예상치 않은 동작**을 했을 때만 실패하도록 해야 합니다. +응용 프로그램 코드가 *무엇을* 했는지를 테스트하는 것이지, 코드가 *어떻게* 되어있는지를 테스트하는 것이 아닙니다. + +- 응용 프로그램이 *무엇을* 했는지를 확인하는 테스트를 **동작 테스트(behavioral tests)**라고 합니다. +- 동작이 동일하게 유지되더라도 응용 프로그램 코드가 변경되면 중단되는 테스트는 **취약한 테스트 (brittle tests)**입니다. + +우리가 `GorillaDB` 라는 바나나 데이터베이스를 가지고 있다고 가정합시다. +`GorillaDB` 는 key-value로 바나나들을 저장하고 있습니다. 우리는 바바나를 다음과 같이 저장할 수 있습니다 : + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +그리고 나중에 디스크에서 바나나를 이렇게 불러올 수 있습니다 : + +```swift +let banana = database.load(key: "my-banana") +``` + +## 취약한 테스트 (Brittle Tests) + +이 동작을 어떻게 테스트해야 할까요? 한 가지 방법은 바나나를 저장한 이후의 데이터베이스 크기를 확인하는 것입니다 : + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +그러나 `GorillaDB` 의 코드가 변경된다고 상상해 보세요. 바나나를 데이터베이스에서 빠르게 읽을 수 있도록 만들려면 가장 자주 사용되는 바나나의 캐시를 유지해야 합니다. `GorillaDB.size` 의 크기는 캐시가 커짐에 따라 점차 커지고, 테스트는 실패할 것입니다. + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 동작 테스트 (Behavioral Tests) + +동작 테스트 작성의 핵심은 애플리케이션 코드에 기대하는 동작을 명확하게 하는 것입니다. + +`testSave_savesTheBananaToTheDatabase` 라는 테스트에서 : 우리가 바나나를 데이터베이스에 "저장" 할 때 우리가 기대하는 동작은 무엇일까요? "저장"이라는 것은 나중에 읽을 수 있다는 의미입니다. 따라서 데이터베이스의 사이즈가 증가하는 것을 테스트하는 것이 아니라, 바나나를 읽을 수 있는지를 테스트해야 합니다. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +동작 테스트를 작성할 때 중요한 포인트 : + +- 정확히 이 애플리케이션 코드가 무엇을 해야 하는지? +- 테스트가 *오직* 동작만을 테스트하는가? + 또는 코드가 다르게 작동함에 따라 실패할 수 있는가? + diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md new file mode 100644 index 0000000..eca7f0d --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/ConfiguringQuick.md @@ -0,0 +1,99 @@ +# Quick의 동작 방식 설정하기 + +`QuickConfiguration` 을 서브클래싱하거나 `QuickConfiguration.Type.configure()` 클래스 메소드를 오버라이드해서 퀵의 동작 방식을 커스터마이징 할 수 있습니다: + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +프로젝트에는 몇 가지 설정이 포함될 수 있습니다. Quick은 이러한 설정이 실행되는 순서에 대해 어떠한 보장을 하지 않습니다. + +## 글로벌 `beforeEach` 와 `afterEach` 클로저 추가하기 + +`QuickConfiguration.beforeEach` 와 `QuickConfiguration.afterEach`를 사용하여 테스트 슈트의 모든 예제 앞이나 뒤에 실행될 클로저를 지정할 수 있습니다 : + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +또한, Quick은 현재 실행 중인 예제와 관련된 메타데이터에 접근하는 것을 허용합니다 : + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md new file mode 100644 index 0000000..0766b77 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingFileTemplates.md @@ -0,0 +1,25 @@ +# Quick 파일 템플릿 설치하기 + +Quick 레포지토리는 Swift와 Objective-C 사양 모두를 위한 파일 템플릿들을 포함하고 있습니다. + +## Alcatraz + +Quick 템플릿은 Xcode 용 패키지 관리자인 [Alcatraz](https://github.com/supermarin/Alcatraz)를 통해 설치할 수 있습니다. 패키지 매니저 창에서 단지 템플릿을 검색만 하면 됩니다. + + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## Rakefile를 통해 수동으로 + +템플릿을 수동으로 설치하려면, 레퍼짓토리를 clone 한 뒤 `templates:install` 명령어를 rake 작업으로 실행하세요. + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +삭제도 간단합니다 : + +```sh +$ rake templates:uninstall +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md new file mode 100644 index 0000000..8596930 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/InstallingQuick.md @@ -0,0 +1,141 @@ +# Quick 설치하기 + +>시작하기 전에, 어떤 버전의 Quick과 Nimble이 당신의 스위프트 버전에 잘 돌아가는지 [이곳](../../README.md#swift-version)에서 확인하세요. + +Quick은 예제들과 예제 그룹을 정의하는 구문을 제공합니다. Nimble은 `expect(...).to` 라는 주장 구문을 제공합니다. 당신은 둘 중 하나, 또는 두 가지 모두를 테스트에 사용할 수 있습니다. + +여기에 Quick을 테스트에 연결할 수 있는 3가지 권장 방법이 있습니다: + +1. [Git 서브 모듈](#Git-서브-모듈) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift 패키지 매니저 (실험적 기능)](#swift-package-manager) + +하나를 선택하고, 아래 지침을 따르세요. 이를 완료한다면, 당신의 test target의 파일에서 `import Quick`으로 Quick을 불러올 수 있어야 합니다. + +## Git 서브 모듈 + +Git 서브 모듈을 사용하여 Quick과 Nimble을 링크하려면: + +1. Quick 서브 모듈을 추가하세요. +2. `.xcworkspace` 가 프로젝트에 아직 없는 경우, 만드세요. ([방법은 이곳에](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. `Quick.xcodeproj`를 프로젝트의 `.xcworkspace` 에 추가하세요. +4. `Nimble.xcodeproj` 또한 프로젝트의 `.xcworkspace` 에 추가하세요. `path/to/Quick/Externals/Nimble` 에 있습니다. Quick의 종속성에서 Nimble을 추가하면 (하위 모듈에서 바로 추가하는 것과 대조적으로), 당신이 사용하고 있는 Quick의 버전에 맞는 Nimble의 올바른 버전을 사용할 수 있게 됩니다. +5. `Quick.framework`와 `Nimble.framework`를 test target 프로젝트의 "Link Binary with Libraries" build phase에 링크시키세요. + +먼저, Git 서브 모듈을 위한 디렉터리가 없다면, 하나 만드세요. +`Vendor` 라는 이름의 디렉터리가 있다고 가정해보겠습니다. + +**Step 1:** Quick과 Nimble을 Git 서브 모듈에서 다운로드 받으세요: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**Step 2:** 위에서 다운로드 한 `Quick.xcodeproj` 와 `Nimble.xcodeproj` 파일을 당신의 `.xcworkspace `에 추가하세요. 예를 들어, `Guanaco.xcworkspace`은 Quick과 Nimble을 사용하여 테스트하는 프로젝트의 워크스페이스 입니다. + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**Step 3:** `Quick.framework` 을 테스트 타겟의`Link Binary with Libraries` build phase에 링크시키세요. 두 개의 `Quick.frameworks` 가 보여야 합니다; macOS용과, iOS용. + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +`Nimble.framework`도 위와 같이 추가하면 끝입니다! + +**서브 모듈 업데이트하기:** Quick이나 Nimble 서브 모듈을 마지막 버전으로 업데이트하기 원한다면, Quick 디렉터리로 들어가서 master 레퍼지토리를 pull 하세요: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +당신의 Git 레퍼지토리는 서브 모듈의 변화를 트래킹할 것입니다. 당신은 Quick 서브 모듈을 업데이트했다는 것을 커밋하기 원할 것입니다. + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**Quick 서브 모듈을 포함하는 레퍼지토리를 Clone 하기:** 다른 사람이 당신의 레퍼지토리를 clone 한 후에, 그들은 서브 모듈 또한 pull 해야 할 것입니다. +`git submodule update` 명령어만 실행하면 됩니다: + +```sh +git submodule update --init --recursive +``` + +Git 서브모듈에 대한 자세한 내용은 [여기](http://git-scm.com/book/en/Git-Tools-Submodules)를 참조하세요. + +## CocoaPods + +먼저, 코코아팟의 버전을 0.36.0 이상의 버전으로 업데이트하세요. Swift를 사용하여 코코아팟을 설치하는 데 필요합니다. + +그리고, Quick과 Nimble을 Podfile 에 추가하세요. 또한, ```use_frameworks!```은 코코아팟에서 Swift를 사용하기 데 필요합니다: + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +마지막으로, 다운로드 후에 Quick과 Nimble을 테스트에 추가하세요: + +```sh +pod install +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +Test target에 "Embedded Binaries" 섹션이 없으므로, 타깃의 프레임워크를 복사하기 위해서는 Build Phase의 "Link Binary With Libraries" 와 "Copy Files" 에 추가해야 합니다. + + > Carthage는 동적 프레임워크를 빌드하기 때문에, 유효한 ID 코드 서명 설정이 필요합니다. + +1. [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) 에 Quick을 추가하세요: + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. `carthage update`를 실행합니다. +3. `Carthage/Build/[platform]/` 디렉터리에서, Quick과 Nimble을 test target의 Build Phase에 있는 "Link Binary With Libraries" 에 추가하세요: + ![](http://i.imgur.com/pBkDDk5.png) + +4. 테스트 타겟에 "Copy Files" 유형의 새 빌드 단계를 만들어 주세요: + ![](http://i.imgur.com/jZATIjQ.png) + +5. "Destination"을 "Frameworks"로 설정하고, 두 framework를 모두 추가해주세요: + ![](http://i.imgur.com/rpnyWGH.png) + +Carthage를 사용하여 의존성을 관리하는 것은 "유일한 방법" 이 아닙니다. +더 자세한 내용은 [Carthage 문서](https://github.com/Carthage/Carthage/blob/master/README.md)를 참조하십시오. + +## [Swift 패키지 매니저](https://github.com/apple/swift-package-manager) +[swift.org](https://swift.org) 오픈 소스 프로젝트의 출현과 함께, Swift는 이제 초기지만, 공식적인 패키지 매니저 툴을 제공합니다. 특히, 처음으로 Quick을 비 Apple 플랫폼에서 사용할 수 있다는 가능성을 제공합니다. Swift 패키지 매니저를 사용하여 Quick 테스트 프로젝트를 사용할 수 있도록 초기 단계가 진행되었지만, 툴이 여전히 많이 개발되어 있지 않아 빈번히 파손될 것으로 예상됩니다. + +추가적인 문서가 더 작성될 때까지, 이 레퍼지토리는 어떻게 Quick이 SwiftPM용`Package.swift` 파일에서 종속성으로 선언되는 방법의 예로서 유용할 수 있습니다. + +https://github.com/Quick/QuickOnLinuxExample + +### (권장하지 않는 방법) 실제 iOS 기기에서 Quick Specs를 실행하기 + +Quick on Device로 작성된 Specs를 실행하려면, `Quick.framework`와 +`Nimble.framework`을 `Embedded Binaries`로 테스트 대상의 `Host Application`에 추가해야 합니다. 임베디드 바이너리로 프레임워크를 추가하면, Xcode가 자동으로 프레임워크와 앱을 연결해 줄 것입니다. + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md new file mode 100644 index 0000000..b32fb56 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/MoreResources.md @@ -0,0 +1,25 @@ +# 더 많은 리소스 + +## Quick Specs 예제 + +Quick은 [GitHub](https://github.com/github)와 [ReactiveCocoa](https://github.com/ReactiveCocoa)를 포함한 많은 회사와 오픈소스 프로젝트, 그리고 개인이 사용하고 있습니다. 예시를 보려면, 다음을 확인하세요: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## OS X와 iOS 앱 용 유닛 테스트에 대한 추가 정보 + +- **[Quality Coding](http://qualitycoding.org/)**: + 유닛 테스트에 초점을 둔 iOS 개발 관련 블로그 +- **[OCMock Tutorials](http://ocmock.org/support/)**: + 테스트에 가짜 개체가 필요할 때 OCMock를 사용하세요. +- **[Nocilla: iOS와 Mac OS X용 놀라운 Http stubbing](https://github.com/luisobo/Nocilla)**: + 이 라이브러리를 사용하여 인터넷에 요청을 보내고 응답을 받는 코드를 테스트하세요. +- **[Pivotal Labs: Jasmine Custom Matchers로 아름다운 Specs 작성하기 ](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**: + Nimble에서 사용자 정의 matcher를 작성하는 방법은 [Nimble 문서](https://github.com/Quick/Nimble)를 참조하세요. diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md new file mode 100644 index 0000000..c3a11fa --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/NimbleAssertions.md @@ -0,0 +1,97 @@ +# Nimble Assertions를 사용하여 테스트를 더욱 간결하게 하기 + +코드가 예상한 대로 작동하지 않을 때, 단위 테스트는 무엇이 문제인가를 **명확하게** 만들어야 합니다. + +원숭이들의 무리가 주어진다면 오직 멍청한 원숭이 무리만 반환하는 함수를 작성해 보세요 : + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +이제 이 함수에 대한 단위 테스트가 있다고 가정을 해 보겠습니다 : + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +테스트는 다음의 실패 메시지와 함께 실패합니다 : + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +실패 했을 때는 많은 정보를 남기는 것이 바람직합니다. 이 실패 메시지의 상태로는 잘 모르겠습니다, "그래, 성공해야 하는데, 무언가가 실패를 했네 — 그래서 뭔데??" 이대로는 우리가 테스트 코드에서 원인을 찾을 때까지 시간을 많이 소비하도록 합니다. + +## 더 나은 오류 메시지, Part 1: 수동으로 `XCTAssert` 실패 메시지 제공하기 + +`XCTAssert` assertions 을 사용하면 사용자 임의 오류 메시지를 지정할 수 있으므로 확실히 도움이 됩니다 : + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +하지만 우리는 오류 메시지를 써야 합니다. + +## 더 나은 오류 메시지, Part 2: Nimble 실패 메시지 + +Nimble은 테스트 assertions를 만들고, 실패 메시지를 읽기 쉽게 만듭니다 : + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +우리는 사용자 임의 실패 메시지를 작성할 필요가 없습니다 — Nimble에서 제공하는 것은 이미 읽기 매우 쉽습니다. + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: VerySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +실패 메시지는 무엇이 잘못되었는지 명확하게 합니다 : 우리는 `silliest()`의 결과에 `kiki` 가 포함될 것으로 예상했지만, 오직 `jane`만 포함하고 있습니다. 이제 무엇이 잘못되었는지 정확히 알고 있으므로 이 이슈를 쉽게 해결할 수 있습니다 : + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble은 많은 다른 assertion을 제공하며, 각각은 큰 실패 메시지를 가지고 있습니다. `XCTAssert` 와는 달리 매번 사용자 임의 실패 메시지를 지정할 필요가 없습니다. + +Nimble assertion의 모든 리스트를 보려면, [Nimble README](https://github.com/Quick/Nimble) 을 확인하세요. +아래는 궁금해하실까 봐 준비한 예제입니다. + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md new file mode 100644 index 0000000..cc5a073 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickExamplesAndGroups.md @@ -0,0 +1,462 @@ +# Quick Example과 Example그룹으로 구성된 테스트 + +Quick에는 **examples**와 **example groups**를 정의하기 위한 특별한 문법이 있습니다. + +*[XCTest를 사용한 효과적인 테스트 : Arrange, Act, 그리고 Assert](ArrangeActAssert.md)* 에서, +좋은 테스트 메소드 이름을 붙이는 것이 매우 중요하다는 것을 배웠습니다. — 테스트가 실패했을 때, 테스트 이름은 응용 프로그램 코드를 수정할지, 테스트 코드를 업데이트할지를 결정하는 데 중요한 자료가 됩니다. + +Quick examples과 example그룹은 두 가지 용도로 사용됩니다: + +1. 서술적인 테스트 이름을 작성하는 것을 장려합니다. +2. 테스트 "환경 구축" 단계에서 코드를 매우 단순하게 합니다. + +## `it`을 사용한 Examples + + `it` 함수로 정의된 Examples는, 코드가 어떻게 동작하는지를 보여주기 위해 assertions를 사용합니다. 이것들은 XCTest의 테스트 메소드와 같습니다. + +`it`은 example의 이름과 클로저, 두 개의 파라미터가 필요합니다. +아래 example은 `Sea.Dolphin` 클래스가 어떻게 동작하는지를 지정합니다. +새로운 돌고래는 영리하고 친절해야 합니다: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +설명을 사용해서 example이 테스트 중인 내용을 명확하게 하세요. +설명은 어떠한 길이의 아무 문자가 가능하며, 영어 이외로 된 언어나 심지어 이모지를 포함한 모든 문자를 사용할 수 있습니다! :v: :sunglasses: + +## `describe`과 `context`를 사용한 Example그룹 + +Example 그룹은 example의 논리적 그룹입니다. Example 그룹은 설정(setup)과 분해(teardown) 코드를 공유할 수 있습니다. + +### 서술하는 클래스와 `describe`를 사용하는 메소드 + +`Dolphin` 클래스의 `click` 메소드의 동작을 지정하기 위해서는 (다시 말해, 메소드의 동작을 테스트하기 위해서는) 몇 가지 `it` example을 `describe` 함수를 이용해서 그룹화시킬 수 있습니다. 비슷한 example을 그룹화하면 spec을 더 쉽게 읽을 수 있습니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +이 두 가지 example이 Xcode에서 실행되면, `describe` 과 `it` 함수들의 설명이 표시될 겁니다: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +다시 말해, 각각의 example이 테스트하고 있는 것이 명확합니다. + +### `beforeEach` 와 `afterEach`를 사용하여 설정 / 해제코드 공유하기 + +Example groups는 example을 더 명확하게 만들어줄 뿐만 아니라, example 그룹 간에 설정 및 해제 코드를 공유하는 데 유용합니다. + +아래 example에서, `beforeEach` 함수는 그룹에서 각 example 앞에 돌고래와 클릭의 새로운 인스턴스를 생성하는 데 사용되었습니다. +이렇게 하면 모든 example에서 각각은 "신선한" 상태가 되었습니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +이러한 공유 설정이 돌고래 예제에서와 큰 차이가 없는 것처럼 보일 수 있지만, 더 복잡한 객체라면 많은 타이핑을 줄여 줄 것입니다! + +각각의 example *다음에* 코드를 실행하려면 `afterEach`를 사용하세요. + +### `context`를 사용하여 조건부 동작 지정하기 + +돌고래는 반항위치 결정법(박쥐 등이 초음파를 발사하여 위치를 알아내는 일)을 위해 클릭을 사용합니다. 그들이 특히 흥미로운 것에 접근하면, 그것이 무엇인지 알기 위해 일련의 클릭을 하게 됩니다. + +테스트는 `click` 메소드가 다른 상황에서 다르게 동작하는 것을 보여줄 필요가 있습니다. 일반적으로, 돌고래는 한 번만 클릭합니다. 하지만 돌고래가 어떤 흥미로운 것에 접근하게 된다면, 여러 번 클릭할 것입니다. + +이것은 `context` 함수를 이용해서 표현할 수 있습니다: 일반적인 `context`와, 돌고래가 흥미로운 것에 가까이 갔을 때의 `context`입니다: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +엄밀히 얘기하면, `context` 키워드는 `describe`과 동의어지만, 사려 깊은 사용은 spec을 더 이해하기 쉽게 만들 것입니다. + +### 테스트 가독성: Quick과 XCTest + +[Effective Tests Using XCTest: Arrange, Act, and Assert](ArrangeActAssert.md)에서, +우리는 테스트 당 하나의 조건이 테스트 코드를 구성하는 좋은 방법이라 알아봤습니다. +XCTest에서는, 긴 테스트 메소드 이름을 사용합니다: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +Quick을 사용하면, 조건을 더 쉽게 읽을 수 있고, 각 example 그룹에 대해 설정을 할 수 있습니다: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 일시적으로 Example이나 그룹을 비활성화하기 + +일시적으로 통과하지 못한 example이나 example 그룹을 비활성화 시킬 수 있습니다. +Example의 이름은 테스트 결과와 함께 출력되지만, 비활성화된 것들은 출력되지 않을 것입니다. + +example이나 group에 `x`를 추가함으로써 비활성화 시킬 수 있습니다: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 포커스 된 Example의 일정 부분을 임시적 실행하기 + +때로는 오직 하나나 몇 가지 Example 에만 집중하는 것이 도움이 됩니다. 하나 또는 두 가지의 example만 실행하는 것은 전체를 실행하는 것보다 빠릅니다. `fit` 함수를 사용해서 하나 또는 두 개만 실행할 수 있습니다. `fdescribe` 이나 `fcontext`를 사용해서 역시 Example 그룹에 집중할 수 있습니다: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## `beforeSuite` 와 `afterSuite`를 사용하여 전역 설정 / 해제하기 + +어떤 테스트 설정은 실행되기 전에 일부 example이 실행되어야 합니다. 이럴 때, `beforeSuite `와 `afterSuite`를 사용합니다. + +아래의 예제에서는, 모든 example이 실행되기 전에 바다의 모든 생물 데이터베이스가 생성됩니다. 모든 example이 완료되면 데이터베이스는 제거됩니다. + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +`beforeSuite`와 `afterSuite`를 원하는 만큼 지정할 수 있습니다. 모든 +`beforeSuite` 클로저는 테스트가 실행되기 전에 실행되고, 모든 +`afterSuite` 클로저는 모든 테스트가 끝난 뒤에 실행될 것입니다. +이 클로저들이 어떤 순서로 실행될지는 보장되지 않습니다. + +## 현재 Example의 메타데이터에 액세스하기 + +현재 실행되고 있는 example에 대한 이름이나, 지금까지 실행되었던 example의 이름을 알고 싶어하는 경우가 있을 수 있습니다. Quick은 `beforeEach`와 `afterEach` 클로저에서 메타데이터에 대한 액세스를 제공합니다. + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md new file mode 100644 index 0000000..7f96a66 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/QuickInObjectiveC.md @@ -0,0 +1,49 @@ +# Objective-C에서 Quick 사용하기 + +Quick은 Swift와 Objective-C 모두에서 똑같이 잘 작동합니다. + +그러나 Objective-C에서 Quick을 사용할 때 유의해야 할 두 가지를 아래에서 설명합니다. + +## Optional 약식 구문 + +Objective-C 파일에서 Quick을 가져오면, `it`과 `itShouldBehaveLike` 같은 매크로와 `context()` 와 `describe()` 같은 함수들이 정의됩니다. + +만약 테스트 중인 프로젝트에서 이러한 이름을 가진 심볼을 정의한다면, 혼란스러운 빌드 오류를 마주할 수 있습니다. 이럴 때에는, 네임스페이스 충돌을 Quick의 Optional "약식" 구문을 해제함으로 피할 수 있습니다: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +`QUICK_DISABLE_SHORT_SYNTAX` 매크로를 Quick을 헤더에 임포트 하기 전에 정의해야 합니다. + +또한, test target의 build configuration에서 매크로를 정의할 수 있습니다: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## 테스트 타겟에는 적어도 하나의 Swift 파일이 포함되어야 합니다 + +Swift stdlib은 테스트 대상에 연결되지 않으므로, test target에 *적어도 하나의* Swift 파일이 포함되어 있지 않으면 Quick이 제대로 실행되지 않습니다. + +적어도 하나의 Swift 파일이 없으면, 테스트는 다음 오류로 인해 조기 종료될 것입니다: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +문제를 해결하기 위해, `SwiftSpec.swift` 라는 빈 테스트 파일을 test target에 추가하세요: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> 이 이슈에 대한 자세한 내용은 https://github.com/Quick/Quick/issues/164를 참조하세요. diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md new file mode 100644 index 0000000..521e83e --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/README.md @@ -0,0 +1,35 @@ +# Documentation + +Quick은 당신의 Swift와 Objective-C가 잘 동작하는지 확인할 수 있도록 도와줍니다. 그러나 Quick을 어떻게 사용하는지 아는 것만으로는 효과적인 방법은 아닙니다. 이 가이드는 Quick, XCTest, 또는 다른 테스트 프레임워크를 사용하는 것뿐만 아니라 효과적인 테스트를 작성하는 것을 도와줄 것입니다. + +각 가이드는 특정 주제를 다루고 있습니다. 유닛 테스트에 대한 사전지식이 없는 분이라면, 아래에 소개된 순서대로 읽는 것을 추천해 드립니다. + +- **[Xcode 프로젝트에 Test 설정하기](SettingUpYourXcodeProject.md)**: + 테스트 파일에서 응용 프로그램 코드를 사용하는 데 문제가 있는 경우 읽어보십시오. +- **[XCTest를 사용한 효과적인 테스트 : Arrange (환경구축), Act (실행), 그리고 Assert (동작 확인)](ArrangeActAssert.md)**: + 코드를 더 빠르고 효과적으로 작성하는 데 도움이 되는 `XCTestCase` 테스트를 작성하는 법을 배우려먼 이 글을 읽어보십시오. +- **[코드를 테스트하지 말고, 동작을 확인하라](BehavioralTesting.md)**: + 어떤 테스트가 속도를 높이고, 어떤 테스트가 속도를 낮추는지 배우려면 이 글을 읽어보십시오. +- **[Nimble Assertions를 사용하여 테스트를 더욱 간결하게 하기](NimbleAssertions.md)**: + Nimble을 사용하여 더 나은 실패 메시지를 생성하는 방법을 배우려면 이 글을 읽어보십시오. 더 나은 실패 메시지는 테스트 실패 원인을 파악하는데 걸리는 시간을 줄여주므로 빠르게 대처할 수 있습니다. +- **[Quick Example과 Example 그룹으로 구성된 테스트](QuickExamplesAndGroups.md)**: + Example과 Example 그룹을 사용하여 Quick이 어떻게 더 효과적인 테스트를 도와주는지 배우려면 이 글을 읽어보십시오. +- **[OS X 와 iOS 앱 테스트](TestingApps.md)**: + AppKit과 UIKit 프레임워크를 사용하는 코드 테스팅을 배우려면 이 글을 읽어 보십시오. +- **[test doubles를 사용한 테스트](TestUsingTestDoubles.md)**: + Test Doubles가 무엇인지, 어떻게 사용하는지 배우려면 이 글을 읽어 보십시오. +- **[Shared Assertions를 사용하여 테스트 상용구 줄이기](SharedExamples.md)**: + 테스트들 사이에 assert 집합을 공유하는 방법에 대해 배우려면 이 글을 읽어 보십시오. +- **[Quick의 동작 방식 설정하기](ConfiguringQuick.md)**: + Quick이 테스트를 실행할 때 동작 방식을 바꾸는 법을 배우려면 이 글을 읽어 보십시오. +- **[Objective-C에서 Quick 사용하기](QuickInObjectiveC.md)**: + Objective-C에서 Quick을 사용하는 데 문제가 있으면 이 내용을 읽어 보십시오. +- **[Quick 설치하기](InstallingQuick.md)**: + Git 서브 모듈, CocoaPods, Carthage, 또는 Swift Package Manager를 사용하여 프로젝트에 Quick을 추가하는 법을 읽어 보십시오. +- **[Quick 파일 템플릿 설치하기](InstallingFileTemplates.md)**: + Quick specs를 더 빨리 작성하게 해주는 파일 템플릿을 설치하는 방법을 배우려면 이 글을 읽어 보십시오. +- **[더 많은 리소스](MoreResources.md)**: + OS X와 iOS 테스트에 대한 추가 리소스 목록입니다. +- **[일반적인 설치 이슈들](Troubleshooting.md)**: + 다른 문제가 발생한다면 이 글을 읽어 보십시오. + diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..518e5fa --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/SettingUpYourXcodeProject.md @@ -0,0 +1,80 @@ +# Xcode 프로젝트에 Test 설정하기 + +Xcode7에서는 Command Line Tool 프로젝트 유형을 제외하고 새 프로젝트를 만들면, 기본적으로 Unit test target이 포함됩니다. [Command Line Tool 프로젝트에 대한 특정 지시사항 보기](#Command-Line-Tool-프로젝트에서-테스트-타겟-설정하기). 단위 테스트를 작성하려면, 필수적으로 Unit test target에서 Main target 코드를 사용할 수 있어야 합니다. + +## Swift 코드를 Swift에서 테스트하기 + +Swift로 작성된 코드를 테스트하려면 다음 두 가지 작업을 수행해야 합니다. + +1. `.xcodeproj` 에서 "Defines Module"을 `YES`로 설정하십시오. + + * Xcode에서 하려면: 프로젝트를 선택하고, "Build Settings"의 "Packaging" 헤더에서, + "Defines Module" 라인을 "Yes"로 선택하세요. 참고: "Packaging" 섹션을 보려면 Build Settings를 "Basic" 대신 "All"로 선택해야 합니다. + +2. `@testable import YourAppModuleName` 을 당신의 유닛테스트에 포함하세요. 그러면 `Public`과 `internal` (기본) 기호가 당신의 테스트에 표시될 것입니다. `private` 기호는 아직 사용할 수 없습니다. + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> Xcode Test Navigator의 Quick과의 통합에는 몇 가지 제약 사항이 있습니다. (open [issue](https://github.com/Quick/Quick/issues/219)). Quick 테스트는 실행될 때까지 내이게이터에 표시되지 않을 것이며, 반복 실행은 예측할 수 없는 방향으로 목록을 재설정하는 경향이 있으며, 테스트는 소스 코드 옆에 표시되지 않습니다. +> 레이더를 Apple에 제출하고, Apple 엔지니어에게 이 기능 요구를 홍보하기 위해 [rdar://26152293](http://openradar.appspot.com/radar?id=4974047628623872)을 언급하세요. + +> 일부 개발자는 Swift 소스 파일을 test target으로 추가할 것을 권장합니다. +> 하지만 이는 [미묘하고, 오류를 진단하기 어려워지므로](https://github.com/Quick/Quick/issues/91), 권장 사항은 아닙니다. + +## Objective-C 코드를 Swift에서 테스트하기 + +1. Bridging header를 Test target에 추가하세요. +2. Bridging header에서, 테스트 해야 할 코드가 있는 파일을 불러옵니다. + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +이제 Swift 테스트 파일에서 `MyClass.h` 에 있는 코드를 사용할 수 있습니다. + +## Swift 코드를 Objective-C에서 테스트하기 + +1. `@objc` 속성을 사용하여 Objective-C로 테스트하려는 Swift 클래스와 함수를 연결합니다. +2. 당신의 단위 테스트에서 모듈의 Swift 헤더들을 불러옵니다. + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## Objective-C 에서 Objective-C 코드를 테스트하기 + +Test target에서 테스트하려는 코드가 정의된 파일을 불러옵니다. + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### Command Line Tool 프로젝트에서 테스트 타겟 설정하기 + +1. 프로젝트 창에서 대상을 프로젝트에 추가합니다. +2. "OS X Unit Testing Bundle"을 선택합니다. +3. 주요 타깃의 스키마를 편집합니다. +4. "Test" 를 선택하고, "Info" 머리말 아래 있는 "+"를 클릭한 뒤, 당신의 테스트 번들을 선택하세요. diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md new file mode 100644 index 0000000..ebc1c9a --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/SharedExamples.md @@ -0,0 +1,116 @@ +# Shared Assertions를 사용하여 테스트 상용구 줄이기 + +때에 따라, 같은 명세서가 여러 객체에 적용될 수 있습니다. + +예를 들어, `Edible`이라는 프로토콜을 생각해 보자. 돌고래가 `Edible` 한 (먹을 수 있는) 음식을 먹으면 돌고래는 행복해집니다. `Mackerel`(고등어) 와 +`Cod`(대구)는 모두 먹을 수 있습니다. Quick은 돌고래가 어느 쪽을 먹어도 기쁘다는 것을 쉽게 테스트할 수 있게 합니다. + +아래 예제는 "먹을 수 있는 것" 에 대한 "공유 명세"를 정의하고, 고등어와 대구가 모두 "먹을 수 있는 것"처럼 행동하도록 지정합니다: + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +공유된 예제들은 임의 개수의 `it`, `context`, `describe` 블록이 포함될 수 있습니다. 이들은 여러 다른 객체에 대해 같은 테스트를 실행할 때 많은 타이핑을 절약할 수 있습니다. + +어떤 경우에는, 추가 컨텍스트가 필요하지 않습니다. Swift에서는, 어떤 매개변수도 사용하지 않는 `sharedExamples` 클로저를 사용할 수 있습니다. 이것은 일종의 전역 상태의 어떤 테스트를 할 때 유용할 수 있습니다: + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Objective-C에서는, 해당 인수를 사용할 계획이 없더라도, `QCKDSLSharedExampleContext`를 사용하는 블록을 전달해야 합니다. 미안하지만, 이것이 쿠키를 부수는 방식이다! +> :cookie: :bomb: + +역시나 `fitBehavesLike` 함수를 이용해서 공유 예제를 "집중" 할 수 있습니다. diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md new file mode 100644 index 0000000..682288a --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/TestUsingTestDoubles.md @@ -0,0 +1,129 @@ +# Mocks 테스트 (모의 테스트) + +## Test doubles + +객체 간 종속성으로 인해 테스트를 작성할 때 문제가 발생할 수 있습니다. 예를 들어, `Tire`에 의존하거나 사용하는 `Car` 클래스가 있다고 가정해봅시다. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests`는 `Tire`라고 불리는 `Car`를 테스트합니다. 이제 `Tire`의 버그로 인해 `CarTests`가 실패할 수 있습니다. (`Car`는 괜찮습니다) 이는 "무엇이 망가졌는가?" 라는 질문에 대답하기 어려울 수 있습니다. + +이러한 문제를 피하려면, `CarTests`의 `Tire` 용 stand-in 객체를 사용할 수 있습니다. 이런 경우, `PerfectTire`라는 `Tire` 용 stand-in 객체를 만듭니다. + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` 는 `Tire` 와 모두 동일한 public 함수와 프로퍼티를 가질 겁니다. 하지만, 이러한 일부 또는 전체의 함수 또는 프로퍼티에 대한 구현은 다를 수 있습니다. + +`PerfectTire` 와 같은 객체는 "test doubles"로 불립니다. Test doubles는 관련 객체의 기능을 독립적으로 테스트하기 위한 "stand-in objects"로 사용됩니다. 여기 몇 가지 종류의 test doubles가 있습니다: + +- Mock 객체: 테스트 객체에서 결과물을 받기 위해 사용됩니다. +- Stub 객체:테스트 객체의 입력을 제공하는 데 사용됩니다. +- Fake 객체: 원래 클래스와 비슷하지만, 단순화된 방식으로 작동합니다. + +Mock 객체의 사용법부터 알아봅시다. + +## Mock + +Mock 객체는 다른 객체와의 정확한 상호 작용을 열거하고, 무언가가 잘못되었을 때를 감지하는 데 초점을 둡니다. Mock 객체는 테스트가 진행되는 도중에 호출되어야 하는 메소드와 mock 객체가 반환해야 하는 값을 (미리) 알아야 합니다. + +Mock 객체는 다음과 같은 이유로 훌륭합니다: + +- 훨씬 더 빨리 테스트합니다. +- 인터넷에 연결되어 있지 않은 경우에도 테스트를 실행합니다. +- 클래스를 종속성과 분리하여 테스트하는 데 중점을 둡니다. + +### Swift에서 Mock 객체로 테스트 작성하기 + +#### Sample app + +예를 들어, 인터넷에서 데이터를 검색하는 앱을 만들어 봅시다: + +* 인터넷의 데이터는 `ViewController`에 표시되어야 합니다. +* 사용자 정의 클래스는 데이터를 가져오는 메서드를 지정하는 `DataProviderProtocol`을 상속합니다. + +`DataProviderProtocol` 은 다음과 같이 정의됩니다: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` 는 인터넷에서 데이터를 가져와 `callback` 클로저를 사용하여 데이터를 반환합니다. + +다음은, `DataProviderProtocol` 프로토콜을 따르는 `DataProvider`클래스 입니다. + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = URL(string: "http://example.com/")! + let session = URLSession(configuration: .default) + let task = session.dataTask(with: url) { + (data, resp, err) in + let string = String(data: data!, encoding: .utf8) + callback(data: string) + } + task.resume() + } +} +``` + +이 시나리오에서, `fetch()` 는 `ViewController` 의 `viewDidLoad()` 메소드에서 호출됩니다. + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### `DataProviderProtocol`의 Mock을 사용하여 테스트 + +`ViewController` 는 `DataProviderProtocol`을 신뢰합니다. 뷰 컨트롤러를 독립적으로 테스트하려면, `DataProviderProtocol` 을 따르는 mock 객체를 만들 수 있습니다. + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + + `fetch()` 가 호출되면, `fetchCalled` 프로퍼티가 `true`로 설정되어, 테스트에서 호출되었음을 확인할 수 있습니다. + +다음 테스트에서는 `ViewController` 가 로드될 때, `dataProvider.fetch() `를 호출하는지 확인합니다. + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvider = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvider = mockProvider + + expect(mockProvider.fetchCalled).to(beFalse()) + + let _ = viewController.view + + expect(mockProvider.fetchCalled).to(beTrue()) + } + } +} +``` + +테스트를 작성하는 것에 관해 관심이 있어서 더 배우고 싶다면, 다음을 참조하세요. . diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md new file mode 100644 index 0000000..c6df101 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/TestingApps.md @@ -0,0 +1,173 @@ +# OS X 와 iOS 앱 테스트 + +*[Xcode 프로젝트에 Test 설정하기](SettingUpYourXcodeProject.md)* +Objective-C 또는 Swift 함수와 클래스를 테스트하기 위해 알아야 할 모든 것을 다룹니다. +이 섹션에서는, `UIViewController` 하위 클래스와 같은 클래스를 테스트하기 위한 몇 가지 추가적인 힌트를 살펴 보겠습니다. + +> 이 주제들을 다루는 라이트닝 토크를 [이곳](https://vimeo.com/115671189#t=37m50s)에서 볼 수 있습니다. (37분 50초쯤 시작합니다) + +## `UIViewController` 라이프 사이클 이벤트 트리거 + +일반적으로, UIKit은 뷰 컨트롤러의 라이프사이클 이벤트를 앱 내에서 표시할 때 트리거합니다. 그러나, `UIViewController`가 테스트 될 때, 이러한 `UIViewController`를 직접 트리거해야 합니다. 다음 3가지 방법 중 하나로 할 수 있습니다: + +1. `UIViewController.viewDidLoad()` 같은 것을 트리거하는 `UIViewController.view`에 액세스하기. +2. `UIViewController.beginAppearanceTransition()` 을 사용하여 대부분의 라이프사이클 이벤트를 트리거하기. +3. `UIViewController.viewDidLoad()` 또는 `UIViewController.viewWillAppear()` 와 같은 메서드를 직접 호출하기. + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## 스토리보드에 정의된 뷰 컨트롤러를 초기화하기 + +스토리보드에 정의된 뷰 컨트롤러를 초기화하기 위해서는, **Storyboard ID**를 뷰 컨트롤러에 지정해야 합니다: + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +그렇게 하면, 테스트 내에서 뷰 컨트롤러를 인스턴스화 할 수 있습니다: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## Button 탭과 같은 UIControl 이벤트 트리거 + +버튼과 다른 UIKit 클래스는 버튼 탭과 같이 프로그래밍적인 방법으로 컨트롤 이벤트를 보낼 수 있는 메소드를 정의하는 `UIControl`을 상속합니다. +버튼을 누를 때 발생하는 동작을 테스트하려면 다음과 같이 작성할 수 있습니다: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` diff --git a/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md b/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md new file mode 100644 index 0000000..e85b4c2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/ko-kr/Troubleshooting.md @@ -0,0 +1,10 @@ +# 일반적인 설치 이슈들 + +다음은 framework를 사용할 때 나타나는 일반적인 문제에 대한 해결책입니다. + +## No such module 'Quick' + +- 이미 `pod install`을 실행한 경우, Xcode workspace를 닫았다가 다시 열어주세요. 그래도 문제가 해결되지 않는다면, 다음을 계속하세요. +- _폴더 전체_ `~/Library/Developer/Xcode/DerivedData`를 삭제합니다. 여기에는 `ModuleCache` 가 포함됩니다. +- Scheme 관리 창에서 scheme을 활성화한 후, `Quick`, `Nimble` 그리고 `Pods-ProjectNameTests` 타깃을 명시적으로 빌드 (`Cmd+B`) 합니다. + diff --git a/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md b/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md new file mode 100644 index 0000000..4e41676 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md @@ -0,0 +1,78 @@ +# Não Teste o Código, Verifique Comportamento + +Testes devem falhar somente se a aplicação **se comportar diferente**. +Eles devem testar *o que* o código da aplicação faz, não *como* faz. + +- Testes que verificam *o que* a aplicação faz são **testes de comportamento**. +- Testes que quebram se o código da aplicação muda, mesmo que o comportamento seja mantido, são **teste frágeis**. + +Vamos supor que temos uma database de bananas, chamada `GorillaDB`. +`GorillaDB` é uma database baseada em chave-valor que guarda bananas. Nós podemos salvar bananas: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +E podemos ler bananas: + +```swift +let banana = database.load(key: "my-banana") +``` + +## Testes Frágeis + +Como podemos testar esse comportamento? Um jeito seria checar o tamanho da database depois de salvar uma banana: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() + let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + + // Assert: The size of the database should have increased by one. + XCTAssertEqual(database.size, originalSize + 1) +} +``` + + +Imagine, no entanto, que o código fonte da `GorillaDB` mude. Para que a operação de leitura de bananas da database seja mais rápida, é mantido um cache com as bananas lidas com maior frequência. `GorillaDB.size` aumenta conforme o tamanho do cache aumenta, e nosso teste falha: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## Testes de Comportamento + +O segredo para escrever testes de comportamento é determinar exatamente o que se espera que o código da aplicação faça. + +No contexto do teste `testSave_savesTheBananaToTheDatabase`: qual é o comportamento esperado quando uma banana é salva na database? "Salvar" implica que essa banana pode ser lida mais tarde. Então, ao invés de testar que o tamanho da database aumenta, nós devemos testar que é possível ler uma banana. + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { + // Arrange: Create a database and get its original size. + let database = GorillaDB() +- let originalSize = database.size + + // Act: Save a banana to the database. + let banana = Banana() + database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +O segredo para escrever testes de comportamento é perguntar: + +- O que exatamente o código dessa aplicação deve fazer? +- O meu teste está verificando *apenas* esse comportamento? Ou o teste pode falhar devido à forma como o código funciona? \ No newline at end of file diff --git a/Carthage/Checkouts/Quick/Documentation/pt-br/README.md b/Carthage/Checkouts/Quick/Documentation/pt-br/README.md new file mode 100644 index 0000000..c170942 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/pt-br/README.md @@ -0,0 +1,39 @@ +# Documentação + +Quick te ajuda a verificar como programas em Swift e Objective-C se comportam. + +Fazê-lo de forma eficaz não é apenas questão de saber como usar Quick. Os guias nesse diretório podem te ajudar a escrever testes eficazes --não apenas usando Quick, mas até mesmo XCTest ou outros framework de teste. + +Cada guia cobre um tópico em particular. Se você é completamente novo a teste unitário, considere lê-los na ordem que são introduzidos abaixo: + +- **[Configurar Testes no seu Xcode Project](SettingUpYourXcodeProject.md)**: + Leia isto se você esta com problemas para usar o código da sua aplicação de dentro dos seus arquivos de teste. +- **[Testes Eficazes Usando XCTest: Arrange, Act e Assert](ArrangeActAssert.md)**: + Leia isto para aprender como escrever `XCTestcase` testes que o ajudarão a escrever código mais rápido e mais eficaz. +- **[Não Teste o Código, Verifique Comportamento](BehavioralTesting.md)**: + Leia isto para aprender que tipos de testes te deixam mais rápido e quais os que só vão acabar te deixando mais devagar. +- **[Testes Limpos Usando Nimble Assertions](NimbleAssertions.md)**: + Leia isto para aprender a usar Nimble para gerar melhores mensagens de falha. + Melhores mensagens de falha ajudam a se mover mais rápido, gastando menos tempo tentando descobrir por que +    um teste falhou. +- **[Testes Organizados com Exemplos Quick e Grupos de Exemplo](QuickExamplesAndGroups.md)**: + Leia isto para aprender como Quick pode ajudar ainda mais a escrever testes eficazes, usando *exemplos* e *grupos de exemplos* +- **[Testando Aplicações OS X e iOS](TestingApps.md)**: + Leia isto para aprender mais sobre testar código que utiliza + AppKit e UIKit frameworks. +- **[Testando com testes dublês](TestUsingTestDoubles.md)**: + Leia isto para aprender o que são testes dublês e como usa-lôs. +- **[Reduzindo Teste Boilerplate com Assertions Compartilhados](SharedExamples.md)**: + Leia isto para aprender como compartilhar conjuntos de assertions entre seus testes. +- **[Configurando como Quick se Comporta](ConfiguringQuick.md)**: + Leia isto para aprender como você pode mudar como Quick se comporta quando roda os sua suite de testes. +- **[Usando Quick com Objective-C](QuickInObjectiveC.md)**: + Leia isto se você esta com problemas para usar Quick em Objective-C. +- **[Instalando Quick](InstallingQuick.md)**: + Leia isto para instruções de como adicionar Quick no seu projeto, usando Git submodules, CocoaPods, Carthage, ou Swift Package Manager. +- **[Instalando Arquivos Templates Quick](InstallingFileTemplates.md)**: +Leia isto para aprender como instalar arquivos templates que deixam escrever Quick specs mais rápidos. +- **[Mais Recursos](MoreResources.md)**: + Uma lista de recursos adicionais sobre testes OS X e iOS. +- **[Troubleshooting](Troubleshooting.md)**: + Leia isto quando você tiver outros problemas. diff --git a/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md b/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md new file mode 100644 index 0000000..eabde35 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md @@ -0,0 +1,116 @@ +# Reduzindo Teste Boilerplate com Assertions Compartilhados + +Em alguns casos, o mesmo conjunto de especificações se aplica a múltiplos objetos. + +Por exemplo, considere um protocol chamado `Edible` (comestível). Quando um golfinho come algo `Edible`, ele fica feliz. `Mackerel` (um tipo de peixe) e `Cod` (bacalhau) são comestíveis. Quick permite testar facilmente que um golfinho fica feliz quando come qualquer um desses peixes. + +O exemplo abaixo define um conjunto de "exemplos compartilhados" para "algo comestível", e especifica que tanto `Mackerel` quanto `Cod` se comportam como "algo comestível": + + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"something edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +Exemplos compartilhados podem incluir qualquer número de blocos `it`, `context` e `describe`. Isso economiza *muito* quando deve-se escrever os mesmos testes para diferentes objetos. + +Em alguns casos, nenhum `context` adicional é necessário. Em Swift, é possível usar `sharedExamples` closures que não recebem parâmetros. Isso pode ser útil quando se esta algum estado global: + + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` + +> Em Objective-C, é necessário passar um bloco que recebe um `QCKDSLSharedExampleContext`, mesmo se esse argumento não for usado. Desculpe, mas é assim que a banda toca! :trumpet: :notes: + +Também é possível "focar" exemplos compartilhados usando a função `fitBehavesLike`. \ No newline at end of file diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md new file mode 100644 index 0000000..fda4f8a --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md @@ -0,0 +1,205 @@ +# 编写高效的 XCTest 测试: Arrange,Act 和 Assert + +当你使用 XCTest,Quick 或者其他测试框架时,你可以遵循下面的模式来编写有效的单元测试: + +1. Arrange - 安排好所有先要条件和输入 +2. Act - 对要测试的对象或方法进行演绎 +3. Assert - 作出预测结果的断言 + +## Arrange, Act, and Assert 三部曲 + +举个例子,假设现在有一个叫 `Banana` 的类: + +```swift +// Banana/Banana.swift + +/** A delicious banana. Tastes better if you peel it first. */ +public class Banana { + private var isPeeled = false + + /** Peels the banana. */ + public func peel() { + isPeeled = true + } + + /** You shouldn't eat a banana unless it's been peeled. */ + public var isEdible: Bool { + return isPeeled + } +} +``` + +现在我们想验证一下 `Banana.peel()` 方法的行为是否跟我们设想的一样: + +```swift +// BananaTests/BananaTests.swift + +class BananaTests: XCTestCase { + func testPeel() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) + } +} +``` + +## 使用明确清晰的方法名字 + +我们的 `testPeel()` 函数可以确保如果 `Banana.peel()` 方法出了问题,我们可以第一时间知道。这通常发生在我们修改了应用的代码后,同时也意味着: + +1. 如果我们意外地写错了代码,我们需要修复它从而让代码正常工作。 +2. 或者我们可能为了增加一个新的功能而改变原有的代码 —— 因此我们需要更改现有的测试代码。 + +如果我们的测试开始出现失败,怎么才能知道是哪一个测试用例失败呢?这可能会让你吃惊,最好的办法是从 **测试方法的名字** 找出端倪。好的测试方法会: + +1. 明确什么是对正在被测试的对象。 +2. 明确什么时候测试应该通过,什么时候测试应该失败。 + +那我们上面的 `testPeel()` 方法的命名清晰吗?我们可以让它变得更清晰: + +```diff +// BananaTests.swift + +-func testPeel() { ++func testPeel_makesTheBananaEdible() { + // Arrange: Create the banana we'll be peeling. + let banana = Banana() + + // Act: Peel the banana. + banana.peel() + + // Assert: Verify that the banana is now edible. + XCTAssertTrue(banana.isEdible) +} +``` + +新的方法命名: + +1. 明确了什么是正在被测试的对象:`testPeel` 指明了正在被测试的是 `Banana.peel()` 方法。 +2. 明确了测试通过的条件:`makesTheBananaEdible` 指明了只要这个测试方法被调用后,香蕉就已经被剥皮(可食用)。 + +## 对条件进行测试 + +假设我们现在可以向别人提供香蕉,有这样一个叫 `offer()` 的函数: + +```swift +// Banana/Offer.swift + +/** Given a banana, returns a string that can be used to offer someone the banana. */ +public func offer(banana: Banana) -> String { + if banana.isEdible { + return "Hey, want a banana?" + } else { + return "Hey, want me to peel this banana for you?" + } +} +``` + +我们的代码做了以下其中一件事: + +1. 给别人一个已经被剥过皮的香蕉。 +2. 或者给别人一个没剥皮的香蕉。 + +现在让我们为这两种情况编写测试: + +```swift +// BananaTests/OfferTests.swift + +class OfferTests: XCTestCase { + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { + // Arrange: Create a banana and peel it. + let banana = Banana() + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { + // Arrange: Create a banana. + let banana = Banana() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +我们的方法名字清晰地指明了测试通过时所应具备的**条件**:在 `whenTheBananaIsPeeled` 测试中,`offer()` 方法应该 `offersTheBanana`。那香蕉没被剥皮的情况呢?好吧,我们也写了另外一个测试来测试这种情况。 + +注意,我们为每个 `if` 条件单独写了一个测试。在我们写测试时,确保每个条件都能被测试,是一个好的模式。如果其中一个条件不再满足,或者需要修改,我们就很容易知道哪个测试需要处理。 + +## 用 `XCTestCase.setUp()` 来编写更简洁的 "Arrange" + +我们的两个 `OfferTests` 测试都包含了相同的 "Arrange" 代码:他们都初始化了一个香蕉。我们应该把初始化方法移到一个单独的地方。为什么? + +1. 现在,假设需要修改 `Banana` 的初始化方法,那么我们就要对每个方法进行修改。 +2. 我们的测试方法会更加简洁 —— 这对于我们是一件好事,当且**仅当**测试方法能更容易被人阅读的时候。 + +现在我们把 `Banana` 的初始化方法移到 `XCTestCase.setUp()` 方法里,这样当每个测试开始时,初始化方法都会被调用。 + +```diff +// OfferTests.swift + +class OfferTests: XCTestCase { ++ var banana: Banana! ++ ++ override func setUp() { ++ super.setUp() ++ banana = Banana() ++ } ++ + func testOffer_whenTheBananaIsPeeled_offersTheBanana() { +- // Arrange: Create a banana and peel it. +- let banana = Banana() ++ // Arrange: Peel the banana. + banana.peel() + + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want a banana?") + } + + func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() { +- // Arrange: Create a banana. +- let banana = Banana() +- + // Act: Create the string used to offer the banana. + let message = offer(banana) + + // Assert: Verify it's the right string. + XCTAssertEqual(message, "Hey, want me to peel this banana for you?") + } +} +``` + +## 在不同的测试里共享 "Arrange" 代码 + +如果你发现你在很多地方都有相同重复的 "arrange" 方法,你可能想定义一个通用的 helper 函数: + +```swift +// BananaTests/BananaHelpers.swift + +internal func createNewPeeledBanana() -> Banana { + let banana = Banana() + banana.peel() + return banana +} +``` + +> 用一个通用函数来定义那些不能被抽象,或不会保存状态的方法。抽象的子类和可修改的状态会使你的测试难以阅读。 + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md new file mode 100644 index 0000000..70a0b51 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md @@ -0,0 +1,75 @@ +# 别测试代码,而应该验证程序的行为 + +测试应该只在程序的**行为和预期的不一样**时,才不通过。测试应该测试程序的代码做了什么,而不是测试程序如何实现。 + +- 验证应用程序做了什么的,叫做**行为测试**。 +- 即使应用程序的行为不发生变化,只要应用程序的代码发生了变化,测试就不通过的,叫做**脆性测试**。 + +假设我们有一个香蕉数据库,叫做 `GorillaDB`。`GorillaDB` 是一个以键-值对来储存香蕉的数据库。我们可以用这样的方式储存香蕉: + +```swift +let database = GorillaDB() +let banana = Banana() +database.save(banana: banana, key: "my-banana") +``` + +之后可以从数据库里取回香蕉: + +```swift +let banana = database.load(key: "my-banana") +``` + +## 脆性测试 + +我们如何测试这个存取的行为呢?一种方式是每当我们储存一根香蕉后就检查数据库的大小: + +```swift +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { +// Arrange: Create a database and get its original size. +let database = GorillaDB() +let originalSize = database.size + +// Act: Save a banana to the database. +let banana = Banana() +database.save(banana: banana, key: "test-banana") + +// Assert: The size of the database should have increased by one. +XCTAssertEqual(database.size, originalSize + 1) +} +``` + +然而,设想一下 `GorillaDB` 的源代码发生了变化。为了从数据库里更快地取出香蕉,数据库预留了一部份缓存空间用于存放经常使用的香蕉。`GorillaDB.size` 就会随着缓存的增加而增加,这样我们的测试就不能通过了: + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/Screenshot_database_size_fail.png) + +## 行为测试 + +编写行为测试的关键,就是准确的定位你想让你的程序代码做什么。 + +在我们的 `testSave_savesTheBananaToTheDatabase` 的测试中:当我们在数据库中储存一根香蕉时,我们所希望程序完成的是一个怎样的行为呢?应该是保存香蕉,即之后可以取回香蕉。因此,我们不该测试数据库大小的增加,而应该测试我们能不能从数据库里取回香蕉。 + +```diff +// GorillaDBTests.swift + +func testSave_savesTheBananaToTheDatabase() { +// Arrange: Create a database and get its original size. +let database = GorillaDB() +- let originalSize = database.size + +// Act: Save a banana to the database. +let banana = Banana() +database.save(banana: banana, key: "test-banana") + +- // Assert: The size of the database should have increased by one. +- XCTAssertEqual(database.size, originalSize + 1) ++ // Assert: The bananas saved to and loaded from the database should be the same. ++ XCTAssertEqual(database.load(key: "test-banana"), banana) +} +``` + +编写行为测试的关键,就在于思考这些问题: + +- 这段程序代码是用来做什么的? +- 我的测试只验证了程序的行为吗?它可能因为代码运行的其他原因而不通过吗? diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md new file mode 100644 index 0000000..fc5ba90 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md @@ -0,0 +1,102 @@ +# 配置 Quick 的行为 + +你可以通过继承 `QuickConfiguration` 并且 +重写 `QuickConfiguration.Type.configure()` 类方法的方式来自定义 Quick 的行为。 + +```swift +// Swift + +import Quick + +class ProjectDataTestConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + // ...set options on the configuration object here. + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(ProjectDataTestConfiguration) + ++ (void)configure:(Configuration *configuration) { + // ...set options on the configuration object here. +} + +QuickConfigurationEnd +``` + +一个项目可能包含多个配置。Quick 不保证这些配置执行的先后顺序。 + +## 添加全局闭包 `beforeEach` 和 `afterEach` + +你可以通过使用 `QuickConfiguration.beforeEach` 和 `QuickConfiguration.afterEach` ,执行测试中每个例子运行前或运行后特定的闭包代码: + +```swift +// Swift + +import Quick +import Sea + +class FinConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { + Dorsal.sharedFin().height = 0 + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +#import "Dorsal.h" + +QuickConfigurationBegin(FinConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEach:^{ + [Dorsal sharedFin].height = 0; + }]; +} + +QuickConfigurationEnd +``` + +另外,Quick 允许你根据当前正在运行的例子,访问元数据: + +```swift +// Swift + +import Quick + +class SeaConfiguration: QuickConfiguration { + override class func configure(configuration: Configuration) { + configuration.beforeEach { exampleMetadata in + // ...use the example metadata object to access the current example name, and more. + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickConfigurationBegin(SeaConfiguration) + ++ (void)configure:(Configuration *)configuration { + [configuration beforeEachWithMetadata:^(ExampleMetadata *data) { + // ...use the example metadata object to access the current example name, and more. + }]; +} + +QuickConfigurationEnd +``` + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md new file mode 100644 index 0000000..7e35365 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md @@ -0,0 +1,26 @@ +# 安装 Quick 文件模板 + +Quick 仓库包含了 Swift 和 Objective-C 规范的文件模板。 + +## Alcatraz + +Quick 模板可以通过 [Alcatraz](https://github.com/supermarin/Alcatraz) 安装,这是一个 Xcode 的包管理器。只需在包管理器里搜索 Quick : + +![](http://f.cl.ly/items/3T3q0G1j0b2t1V0M0T04/Screen%20Shot%202014-06-27%20at%202.01.10%20PM.png) + +## 使用 Rakefile 手动安装 + +如果想手动安装模板,那么只需克隆仓库并运行 rake 命令 `templates:install` : + +```sh +$ git clone git@github.com:Quick/Quick.git +$ rake templates:install +``` + +若要卸载模板,可以运行命令: + +```sh +$ rake templates:uninstall +``` + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md new file mode 100644 index 0000000..2f54b0a --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md @@ -0,0 +1,157 @@ +# 安装 Quick + +> **如果你的 Xcode 版本是7.1,** 请使用新的 Quick--`v0.9.0` 写测试代码。 +> 新发布的版本是基于 `swift-2.0` 这个分支开发的。 + + + +Quick 提供了定义例子和例子群的语法。 Nimble 提供了如 `expect(...).to` 的断言语法。 在写测试代码的时候,你可以使用它们中的任意一个或者同时使用它们。 + +下面是几种主要的方法,用来添加 Quick 支持: + +1. [Git Submodules](#git-submodules) +2. [CocoaPods](#cocoapods) +3. [Carthage](#carthage) +4. [Swift Package Manager (experimental)](#swift-package-manager) + +你可以选择其中一种方法,并按照下面的步骤进行。完成之后,就可以通过 `import Quick` 使你的测试支持 Quick 。 + +## Git Submodules + +通过以下步骤可以使用 Git 的子模块(submodules) 为项目添加 Quick 和 Nimble : + +1. 添加子模块 Quick。 +2. 为你的项目新建一个 `.xcworkspace` 文件,如果原本已经有这个文件,则跳过此步骤。 ([如何添加请看这里](https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_an_Existing_Project_to_a_Workspace.html)) +3. 把 `Quick.xcodeproj` 添加到项目的 `.xcworkspace`中。 +4. 把 `Nimble.xcodeproj` 添加到项目的 `.xcworkspace`中。它所在的目录是: `path/to/Quick/Externals/Nimble`。 通过从 Quick 的依赖库中添加 Nimble (而不是直接添加为子模块),可以确保无论所用的 Quick 是什么版本,都能使用正确版本的 Nimble 。 +5. 把 `Quick.framework` 和 `Nimble.framework` 添加到项目 "build phase" 选项页的 "Link Binary with Libraries" 列表中。 + +首先,你需要有一个 Git 子模块的目录,如果没有的话,就创建一个。假设这个目录的名称是 "Vendor" 。 + +**第一步:** 下载 Quick 和 Nimble 作为 Git 的子模块: + +```sh +git submodule add git@github.com:Quick/Quick.git Vendor/Quick +git submodule add git@github.com:Quick/Nimble.git Vendor/Nimble +git submodule update --init --recursive +``` + +**第二步:** 把下载完的 `Quick.xcodeproj` 和 `Nimble.xcodeproj` 文件添加到项目的 `.xcworkspace` 上。 例如:下图是 `Guanaco.xcworkspace` 已经添加了 Quick 和 Nimble : + +![](http://f.cl.ly/items/2b2R0e1h09003u2f0Z3U/Screen%20Shot%202015-02-27%20at%202.19.37%20PM.png) + +**第三步:** 把 `Quick.framework` 添加到测试目标(target)的 `Link Binary with Libraries` 列表中。你会发现有两个 `Quick.frameworks`;其中一个是 OS X 平台的,另一个是 iOS 平台的。 + +![](http://cl.ly/image/2L0G0H1a173C/Screen%20Shot%202014-06-08%20at%204.27.48%20AM.png) + +重复上面的步骤,添加 `Nimble.framework`。 + +**更新子模块:** 如果你想把 Quick 和 Nimble 模块升级到最新版本,你可以在 Quick 目录下使用 `pull` 来更新,如下: + +```sh +cd /path/to/your/project/Vendor/Quick +git checkout master +git pull --rebase origin master +``` + +你的 Git 仓库会自动同步更改到子模块中。如果你想确保已经更新了 Quick 子模块,那么可以这样: + +```sh +cd /path/to/your/project +git commit -m "Updated Quick submodule" +``` + +**克隆一个包含有 Quick 子模块的仓库:** 当其他人克隆了你的仓库后,他们会同时拥有这些子模块。 +他们可以运行 `git submodule update` 命令: + +```sh +git submodule update --init --recursive +``` + +更多关于子模块的内容,可以参考[这里](http://git-scm.com/book/en/Git-Tools-Submodules)。 + +## CocoaPods + +首先,请把 CocoaPods 升级到0.36或者更高的版本,这样才能在 Swift 下使用 CocoaPods 。 + +然后在你的 Podfile 中添加 Quick 和 Nimble 。并且为了在 Swift 中使用 CocoaPods ,记得加上这一行: ```use_frameworks!``` 。 + +```rb + +# Podfile + +use_frameworks! + +def testing_pods + pod 'Quick' + pod 'Nimble' +end + +target 'MyTests' do + testing_pods +end + +target 'MyUITests' do + testing_pods +end +``` + +最后,下载并将 Quick 和 Nimble 导入到你的测试中: + +```sh +pod install +``` + +### 使用 Swift 1.2 ? + +最近发布的 Quick (0.4.0) 适用于 Swift 2 (Xcode 7),但是 Nimble (1.0.0) 适用于 Swift 1.2 (Xcode 6)。 + +如果你想在 Xcode 6 中使用它们,请使用以下这段代码: + +```sh +target 'MyTests' do + use_frameworks! + pod 'Quick', '~>0.3.0' + pod 'Nimble', '~>1.0.0' +end +``` + +## [Carthage](https://github.com/Carthage/Carthage) + +在一个项目中,测试所在的目标(target)并没有 "Embedded Binaries" 这部分内容, 因此必须把框架添加到目标的 "Link Binary With Libraries" 里,并且在 build phase 选项页中新建一条 "Copy Files" 把它们复制到目标的框架列表中。 + + > 因为 Carthage 生成的是动态的框架,所以你需要有一个合法的身份标识。 + +1. 在 [`Cartfile.private`](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfileprivate) 中添加 Quick ,如下: + + ``` + github "Quick/Quick" + github "Quick/Nimble" + ``` + +2. 运行 `carthage update`。 +3. 从 `Carthage/Build/[platform]/` 目录下, 找到 Quick 框架和 Nimble 框架,把它们添加到测试目标的 "Link Binary With Libraries" 列表中: + ![](http://i.imgur.com/pBkDDk5.png) + +4. 在你的测试目标下新建一条 "Copy Files" : + ![](http://i.imgur.com/jZATIjQ.png) + +5. 将 "Destination" 设为 "Frameworks",然后添加这两个框架: + ![](http://i.imgur.com/rpnyWGH.png) + +注意,这并不是使用 Carthage 来管理依赖的唯一方法。更多的方法请参考 [Carthage documentation](https://github.com/Carthage/Carthage/blob/master/README.md)。 + +## [Swift Package Manager](https://github.com/apple/swift-package-manager) +随着 [swift.org](https://swift.org) 上一个开源项目的出现, Swift 现在有了一个官方的包管理器。 尽管它刚问世不久,但是它首次使在非苹果平台上使用 Quick 成为了可能。经过初期的开发,现在已经可以利用 Swift Package Manager 为测试项目添加 Quick 支持了。但是由于这个包管理器正在开发中,在使用的过程中可能会出现一些问题。 + +在更新的帮助文档发布之前,这个项目阐述了如何在 SwiftPM 的 `Package.swift` 中添加 Quick 。 + +https://github.com/Quick/QuickOnLinuxExample + +### (不建议) 在真实的iOS设备上运行用Quick书写的代码 + +为了在设备上运行 Quick 形式的代码,你需要把 `Quick.framework` 和 `Nimble.framework` 作为 `Embedded Binaries` 添加到项目目标的 `Host Application` 里。 当以二进制文件的形式把框架添加到 Xcode 中,Xcode 会自动为 App 添加 Quick 框架。 + +![](http://indiedev.kapsi.fi/images/embed-in-host.png) + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md new file mode 100644 index 0000000..0a9ed84 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md @@ -0,0 +1,23 @@ +# 更多资源 + +## Quick Specs 的例子 + +很多公司、开源项目和独立开发者都使用了 Quick ,包括 [GitHub](https://github.com/github) 和 [ReactiveCocoa](https://github.com/ReactiveCocoa)。具体例子请参考以下链接: + +- https://github.com/ReactiveCocoa/ReactiveCocoa +- https://github.com/github/Archimedes +- https://github.com/libgit2/objective-git +- https://github.com/jspahrsummers/RXSwift +- https://github.com/artsy/eidolon +- https://github.com/AshFurrow/Moya +- https://github.com/nerdyc/Squeal +- https://github.com/pepibumur/SugarRecord + +## 关于 OS X 和 iOS 应用单元测试的更多信息 + +- **[Quality Coding](http://qualitycoding.org/)**:一个关注单元测试的 iOS 开发博客。 +- **[OCMock Tutorials](http://ocmock.org/support/)**:当你需要在测试中使用伪对象时,使用 OCMock 。 +- **[Nocilla: Stunning HTTP stubbing for iOS and Mac OS X](https://github.com/luisobo/Nocilla)**:使用这个库来测试那些与互联网进行数据交换的代码。 +- **[Pivotal Labs: Writing Beautiful Specs with Jasmine Custom Matchers](http://pivotallabs.com/writing-beautiful-specs-jasmine-custom-matchers/)**:参考 [the Nimble documentation](https://github.com/Quick/Nimble) ,了解如何用 Nimble 编写自定义的匹配器。 + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md new file mode 100644 index 0000000..a1b0197 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md @@ -0,0 +1,100 @@ +# 使用 Nimble 断言,让测试更清晰 + +当代码不能如预期那样正常运行时,单元测试应该能够反映出问题的所在。 + +例如,下面这个函数能够从所给的一组猴子中筛选并返回其中的傻猴子: + +```swift +public func silliest(monkeys: [Monkey]) -> [Monkey] { + return monkeys.filter { $0.silliness == .verySilly } +} +``` + +现在有一个针对这个函数的单元测试: + +```swift +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) + XCTAssertTrue(contains(sillyMonkeys, kiki)) +} +``` + +这个测试运行失败,并返回以下信息: + +``` +XCTAssertTrue failed +``` + +![](http://f.cl.ly/items/1G17453p47090y30203d/Screen%20Shot%202015-02-26%20at%209.08.27%20AM.png) + +我们无法从失败信息中获得有用的东西,只能说:“好吧,原本预期为真的表达式,现在却为假。但这是为什么呢?” +像这样的困惑会降低我们的效率,因为我们现在不得不花时间理解这些测试代码。 + +## 更好的失败返回信息,第一部分:手动设定 `XCTAssert` 的返回信息 + +`XCTAssert` 这个断言(Assertion)允许我们设定运行失败时的返回信息(下面简称“返回信息”),这当然有一定的作用: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki)) ++ XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") +} +``` + +但是,我们就不得不亲自设置这些返回信息。 + +## 更好的失败返回信息,第二部分:Nimble 的返回信息 + +Nimble 能让你的测试断言及其返回信息更便于阅读: + +```diff +func testSilliest_whenMonkeysContainSillyMonkeys_theyreIncludedInTheResult() { + let kiki = Monkey(name: "Kiki", silliness: .extremelySilly) + let carl = Monkey(name: "Carl", silliness: .notSilly) + let jane = Monkey(name: "Jane", silliness: .verySilly) + let sillyMonkeys = silliest([kiki, carl, jane]) +- XCTAssertTrue(contains(sillyMonkeys, kiki), "Expected sillyMonkeys to contain 'Kiki'") ++ expect(sillyMonkeys).to(contain(kiki)) +} +``` + +我们不需要再亲自设置返回信息,因为 Nimble 提供的信息已经非常清楚了: + +``` +expected to contain , + got <[Monkey(name: Jane, silliness: VerySilly)]> +``` + +![](http://f.cl.ly/items/3N2e3g2K3W123b1L1J0G/Screen%20Shot%202015-02-26%20at%2011.27.02%20AM.png) + +这个返回信息清楚地点明了出错的地方:预期中 `kiki` 应该包含在 `silliest()` 的返回值里面,但是实际的返回值只包含 `jane` 。现在我们知道问题出在哪了,因此很容易解决问题: + +```diff +public func silliest(monkeys: [Monkey]) -> [Monkey] { +- return monkeys.filter { $0.silliness == .verySilly } ++ return monkeys.filter { $0.silliness == .verySilly || $0.silliness == .extremelySilly } +} +``` + +Nimble 提供了很多种类的断言,每个断言都带有清晰的返回信息。与 `XCTAssert` 不同,你不需要每次都亲自设定返回信息。 + +完整的 Nimble 断言列表,请参考 [Nimble README](https://github.com/Quick/Nimble) 。 +下面是一些例子,先睹为快: + +```swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md new file mode 100644 index 0000000..255c278 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md @@ -0,0 +1,461 @@ +# 用 Quick 例子和例子群组织测试 + +Quick 使用特殊的语法定义**例子(examples)**和**例子群(example groups)**。 + +在*[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)*,我们了解了一个好的测试方法名称是至关重要的,尤其是当测试失败时。它能够帮助我们判断是修改程序代码或者是更新测试内容。 + +Quick 的例子和例子群主要有两个目的: + +1. 它们促使你使用具有描述性的测试名称。 +2. 它们极大地简化了 Arrange 步骤的测试代码。 + +## 例子:使用 `it` + +定义了 `it` 函数的例子,使用断言代码指明了程序应有的行为。这些就像 XCTest 中的测试方法一样。 + +`it` 函数有两个参数:例子的名称和闭包。下面这个例子具体说明了 `Sea.Dolphin` 类应有的行为。 +一只新的海豚(dolphin)应该是聪明(smart)且友好(friendly)的: + +```swift +// Swift + +import Quick +import Nimble +import Sea + +class DolphinSpec: QuickSpec { + override func spec() { + it("is friendly") { + expect(Dolphin().isFriendly).to(beTruthy()) + } + + it("is smart") { + expect(Dolphin().isSmart).to(beTruthy()) + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +it(@"is friendly", ^{ + expect(@([[Dolphin new] isFriendly])).to(beTruthy()); +}); + +it(@"is smart", ^{ + expect(@([[Dolphin new] isSmart])).to(beTruthy()); +}); + +QuickSpecEnd +``` + +用描述性的语言使例子所测试的内容清晰明了。 +描述性的语言可以是任意长度、任意字符的,涵盖了英语以及其他语言的字符,甚至可以是表情符号!:v: :sunglasses: + +## 例子群:使用 `describe` 和 `context` + +例子群是按一定逻辑关系组织的例子。例子群里可以共享配置(setup)和卸载(teardown)代码。 + +### 使用 `describe` 描述类和方法 + +为了具体说明 `Dolphin` 类中 `click` 方法的行为 —— 换句话说,为了验证这个方法可用 —— 我们可以把多个 `it` 例子用 `describe` 函数组织成为一个群。把相同的例子组织在一起能更方便阅读: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + describe("its click") { + it("is loud") { + let click = Dolphin().click() + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + let click = Dolphin().click() + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + describe(@"its click", ^{ + it(@"is loud", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + Click *click = [[Dolphin new] click]; + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +当这两个例子在 Xcode 中运行的时候,它们会从 `describe` 和 `it` 函数中输出一些描述性的语言: + +1. `DolphinSpec.a_dolphin_its_click_is_loud` +2. `DolphinSpec.a_dolphin_its_click_has_a_high_frequency` + +显然,这两个测试各自测试的内容都很清晰明了。 + +### 使用 `beforeEach` 和 `afterEach` 共享配置/卸载代码 + +例子群不仅使它包含的例子更清晰易懂,还有助于在群里共享配置和卸载的代码。 + +在下面的这个示例里,例子群中的每一个例子前面,都用 `beforeEach` 这个函数创建一种新类型的海豚以及它特定的叫声。 +这就保证了对每个例子进行了初始化: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { + dolphin = Dolphin() + } + + describe("its click") { + var click: Click! + beforeEach { + click = dolphin.click() + } + + it("is loud") { + expect(click.isLoud).to(beTruthy()) + } + + it("has a high frequency") { + expect(click.hasHighFrequency).to(beTruthy()) + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ + dolphin = [Dolphin new]; + }); + + describe(@"its click", ^{ + __block Click *click = nil; + beforeEach(^{ + click = [dolphin click]; + }); + + it(@"is loud", ^{ + expect(@(click.isLoud)).to(beTruthy()); + }); + + it(@"has a high frequency", ^{ + expect(@(click.hasHighFrequency)).to(beTruthy()); + }); + }); +}); + +QuickSpecEnd +``` + +对于海豚这个例子来说,像这样共享配置代码并不是一个很大的工程。但是对于更复杂的对象,共享代码能够省去大量写代码的时间! + +如果想在每个例子后面执行特定的代码,可以使用 `afterEach`。 + +### 使用 `context` 指定条件的行为 + +海豚使用叫声进行回声定位。当接近了它们感兴趣的东西时,海豚会发出一系列的超声波对其进行更准确的探测。 + +这个测试需要展示在不同环境下,`click` 方法的不同行为。通常,海豚只叫(click)一声。但是当海豚接近它们感兴趣的东西时,它会发出很多次叫声。 + +这种情况可以用 `context` 函数来表示:一个 `context` 代表正常情况,另一个 `context` 代表海豚接近感兴趣的东西: + +```swift +// Swift + +import Quick +import Nimble + +class DolphinSpec: QuickSpec { + override func spec() { + describe("a dolphin") { + var dolphin: Dolphin! + beforeEach { dolphin = Dolphin() } + + describe("its click") { + context("when the dolphin is not near anything interesting") { + it("is only emitted once") { + expect(dolphin.click().count).to(equal(1)) + } + } + + context("when the dolphin is near something interesting") { + beforeEach { + let ship = SunkenShip() + Jamaica.dolphinCove.add(ship) + Jamaica.dolphinCove.add(dolphin) + } + + it("is emitted three times") { + expect(dolphin.click().count).to(equal(3)) + } + } + } + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickSpecBegin(DolphinSpec) + +describe(@"a dolphin", ^{ + __block Dolphin *dolphin = nil; + beforeEach(^{ dolphin = [Dolphin new]; }); + + describe(@"its click", ^{ + context(@"when the dolphin is not near anything interesting", ^{ + it(@"is only emitted once", ^{ + expect(@([[dolphin click] count])).to(equal(@1)); + }); + }); + + context(@"when the dolphin is near something interesting", ^{ + beforeEach(^{ + [[Jamaica dolphinCove] add:[SunkenShip new]]; + [[Jamaica dolphinCove] add:dolphin]; + }); + + it(@"is emitted three times", ^{ + expect(@([[dolphin click] count])).to(equal(@3)); + }); + }); + }); +}); + +QuickSpecEnd +``` + +严格地说,`context` 是 `describe` 的一种同义的表达,但是像这样有目的地使用能够让你的代码更容易理解。 + +### 测试的可读性:Quick 和 XCTest + +在*[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)*里,我们知道了对每种情况进行一个测试能够很方便地组织测试代码。 +在 XCTest 里,这样做会导致出现冗长的测试方法名称: + +```swift +func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() { + // ... +} +``` + +使用 Quick ,每种情况会更容易阅读,并且我们能够为每一个例子群进行配置: + +```swift +describe("a dolphin") { + describe("its click") { + context("when the dolphin is near something interesting") { + it("is emitted three times") { + // ... + } + } + } +} +``` + +## 临时禁用例子或例子群 + +你可以临时禁用那些测试不通过的例子和例子群。 +这些例子的名称会随着测试结果一起打印在控制台里,但它们并不运行。 + +通过添加前缀 `x` 就能禁用例子或例子群: + +```swift +// Swift + +xdescribe("its click") { + // ...none of the code in this closure will be run. +} + +xcontext("when the dolphin is not near anything interesting") { + // ...none of the code in this closure will be run. +} + +xit("is only emitted once") { + // ...none of the code in this closure will be run. +} +``` + +```objc +// Objective-C + +xdescribe(@"its click", ^{ + // ...none of the code in this closure will be run. +}); + +xcontext(@"when the dolphin is not near anything interesting", ^{ + // ...none of the code in this closure will be run. +}); + +xit(@"is only emitted once", ^{ + // ...none of the code in this closure will be run. +}); +``` + +## 临时运行一部分例子 + +在某些情况下,只关注一个或几个例子有助于测试。毕竟只运行一两个例子比运行整个测试快多了。通过使用 `fit` 函数,你可以只运行一两个例子。你还可以使用 `fdescribe` 或 `fcontext` 把测试重点放在一个例子群: + +```swift +fit("is loud") { + // ...only this focused example will be run. +} + +it("has a high frequency") { + // ...this example is not focused, and will not be run. +} + +fcontext("when the dolphin is near something interesting") { + // ...examples in this group are also focused, so they'll be run. +} +``` + +```objc +fit(@"is loud", { + // ...only this focused example will be run. +}); + +it(@"has a high frequency", ^{ + // ...this example is not focused, and will not be run. +}); + +fcontext(@"when the dolphin is near something interesting", ^{ + // ...examples in this group are also focused, so they'll be run. +}); +``` + +## 使用 `beforeSuite` 和 `afterSuite` 进行全局配置/卸载 + +有一些测试的配置需要在所有例子运行之前进行。对于这种情况,可以使用 `beforeSuite` 和 `afterSuite` 。 + +下面的示例展示了在所有其他例子运行之前,创建一个包含了海洋中所有生物的数据库。当所有例子运行结束的时候,这个数据库就被卸载: + +```swift +// Swift + +import Quick + +class DolphinSpec: QuickSpec { + override func spec() { + beforeSuite { + OceanDatabase.createDatabase(name: "test.db") + OceanDatabase.connectToDatabase(name: "test.db") + } + + afterSuite { + OceanDatabase.teardownDatabase(name: "test.db") + } + + describe("a dolphin") { + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; + +QuickSpecBegin(DolphinSpec) + +beforeSuite(^{ + [OceanDatabase createDatabase:@"test.db"]; + [OceanDatabase connectToDatabase:@"test.db"]; +}); + +afterSuite(^{ + [OceanDatabase teardownDatabase:@"test.db"]; +}); + +describe(@"a dolphin", ^{ + // ... +}); + +QuickSpecEnd +``` + +你可以添加多个 `beforeSuite` 和 `afterSuite` 。所有的 +`beforeSuite` 闭包都会在其它测试运行前执行,同样,所有的 +`afterSuite` 闭包都会在其它测试运行结束后执行。 +但是这些闭包并不一定按先后顺序执行。 + +## 访问当前例子的元数据 + +在某些情况下,你会想知道当前运行的例子的名称,或者目前已经运行了多少例子。Quick 提供了闭包 `beforeEach` 和 `afterEach` ,通过这些闭包,可以访问元数据。 + +```swift +beforeEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) is about to be run.") +} + +afterEach { exampleMetadata in + println("Example number \(exampleMetadata.exampleIndex) has run.") +} +``` + +```objc +beforeEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l is about to be run.", (long)exampleMetadata.exampleIndex); +}); + +afterEachWithMetadata(^(ExampleMetadata *exampleMetadata){ + NSLog(@"Example number %l has run.", (long)exampleMetadata.exampleIndex); +}); +``` + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md new file mode 100644 index 0000000..22318a0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md @@ -0,0 +1,52 @@ +# 在 Objective-C 中使用 Quick + +Quick 既支持 Swift ,也支持 Objective-C 。 + +但是,在 Objective-C 下使用 Quick 时,有以下两点需要注意。 + +## 可选的速记语法 + +在 Objective-C 文件中导入的 Quick 框架,包含了名为 `it` 和 +`itShouldBehaveLike` 的宏,还包含了名为 `context()` 和 `describe()` 的函数。 + +如果你在测试项目的时候,也定义了同名的量或者函数,那么就会出现错误。因此,这种情况下,你可以通过禁用 Quick 的可选速记语法来避免命名冲突: + +```objc +#define QUICK_DISABLE_SHORT_SYNTAX 1 + +@import Quick; + +QuickSpecBegin(DolphinSpec) +// ... +QuickSpecEnd +``` + +注意,必须在 `@import Quick;` 之前,定义宏:`QUICK_DISABLE_SHORT_SYNTAX` 。 + +当然,你也可以选择在测试目标(target)的设置里面定义宏: + +![](http://d.twobitlabs.com/VFEamhvixX.png) + +## 你的测试目标必需至少包含一个 Swift 文件 + +如果你的测试目标没有*至少包含一个 Swift 文件*,那么 Swift 标准库就不会链接到你的测试目标,因而会导致 Quick 无法正常编译。 + +当没有至少包含一个 Swift 文件时,测试运行后就会终止并且返回以下错误: + +``` +*** Test session exited(82) without checking in. Executable cannot be +loaded for some other reason, such as a problem with a library it +depends on or a code signature/entitlements mismatch. +``` + +只需要在测试目标下添加一个空的 Swift 文件,如 `SwiftSpec.swift` 就可以解决这个问题: + +```swift +// SwiftSpec.swift + +import Quick +``` + +> 更多关于这个问题的细节,请参考 https://github.com/Quick/Quick/issues/164 。 + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md new file mode 100644 index 0000000..2c48f4c --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md @@ -0,0 +1,18 @@ +# 文档 + +Quick 能够帮助你验证你的 Swift 和 Objective-C 程序的行为。然而,能提高你的测试技巧的不仅仅是了解如何使用 Quick。下面这些指南能够帮助你更有效地写测试 —— 不仅是和 Quick 相关的,更包括 XCTest 还有其他的测试框架。 + +每份指南都有一个主题。如果你对单元测试完全陌生,建议你按照从上往下的顺序阅读。 + +- **[在项目中添加测试](SettingUpYourXcodeProject.md)**:如果你遇到在项目中构建测试的问题,请阅读这份指南。 +- **[编写高效的 XCTest 测试: Arrange,Act 和 Assert](ArrangeActAssert.md)**:阅读这份指南来了解如何更高效快速地编写 `XCTestCase` 测试。 +- **[不要测试代码,而应该测试行为](BehavioralTesting.md)**:通过这份指南你能学习到哪些是好的测试,哪些是不好的测试。 +- **[测试 OS X 和 iOS 应用](TestingApps.md)**:了解如何为使用 AppKit 和 UIKit 框架的代码编写测试。 +- **[使用测试替身进行测试](TestUsingTestDoubles.md)**:阅读这份指南来了解什么是测试替身,以及如何使用它们。 +- **[使用 Shared Assertion 来复用测试模板代码](SharedExamples.md)**:学习如何在测试中共享测试代码。 +- **[配置 Quick 的行为](ConfiguringQuick.md)**:阅读这份指南来了解如何在运行测试代码时改变 Quick 的行为。 +- **[在 Objective-C 中使用 Quick](QuickInObjectiveC.md)**:如果你在 Objective-C 项目使用 Quick 的过程中遇到了困难,请阅读这份指南。 +- **[安装 Quick](InstallingQuick.md)**:通过这份指南了解在项目中添加 Quick 的方法:Git submodules,CocoaPods,Carthage 和 Swift Package Manager 。 +- **[安装 Quick 文件模板](InstallingFileTemplates.md)**:阅读这份指南来了解如何安装文件模板以提高编写 Quick specs 的效率。 +- **[更多资料](MoreResources.md)**:更多关于 OS X 和 iOS 测试的资源。 +- **[常见的问题](Troubleshooting.md)**:当你遇到问题的时候,请阅读这份指南。 diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..e902c6f --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md @@ -0,0 +1,75 @@ +# 在项目中添加测试 + +除了命令行项目以外,当你在 Xcode 7 中创建新项目时,单元测试 Target 默认是包含的。[为命令行项目设置测试 Target](#setting-up-a-test-target-for-a-command-line-tool-project) 要编写单元测试,你需要能够在测试 Target 中使用主 target 代码。 + +## 用 Swift 测试 Swift 项目代码 + +为了测试用 Swift 写的代码,你需要做以下两件事: + +1. 将 `.xcodeproj` 中的 "defines module" 设置为 `YES`。 + + * Xcode 中具体操作方法:选中你的项目,选择 "Build Settings" 选项列表,选中 "Defines Modules" 行,修改其值为 "Yes"。 + +2. 在单元测试中添加 `@testable import YourAppModuleName`。这会把所有 `public` 和 `internal` (默认访问修饰符) 修饰符暴露给测试代码。但 `private` 修饰符仍旧保持私有。 + +```swift +// MyAppTests.swift + +import XCTest +@testable import MyModule + +class MyClassTests: XCTestCase { + // ... +} +``` + +> 一些开发者提倡添加 Swift 源文件至测试 target。然而这会导致以下问题 [subtle, hard-to-diagnose errors](https://github.com/Quick/Quick/issues/91),所以并不推荐。 + +## 使用 Swift 测试 Objective-C 项目代码 + +1. 给你的测试 target 添加 bridging header 文件。 +2. 在 bridging header 文件中,引入待测试的代码文件。 + +```objc +// MyAppTests-BridgingHeader.h + +#import "MyClass.h" +``` + +现在就可以在 Swift 测试文件中使用 `MyClass.h` 中的代码了。 + +## 使用 Objective-C 测试 Swift 项目代码 + +1. 使用 `@objc` 桥接需要使用 Objective-C 测试的 Swift 类和方法。 +2. 在单元测试中引入模块的 Swift 头文件。 + +```objc +@import XCTest; +#import "MyModule-Swift.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +## 使用 Objective-C 测试 Objective-C 项目代码 + +在测试 target 中引入待测试的代码文件: + +```objc +// MyAppTests.m + +@import XCTest; +#import "MyClass.h" + +@interface MyClassTests: XCTestCase +// ... +@end +``` + +### 为命令行项目设置测试 Target + +1. 在项目窗格中添加一个项目target。 +2. 选择 "OS X Unit Testing Bundle"。 +3. 编辑主target的 scheme。 +4. 选中 "Test" 条目,单击 "Info" 下的 "+",选择需要测试的 bundle。 diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md new file mode 100644 index 0000000..ec87138 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md @@ -0,0 +1,113 @@ +# 使用 Shared Assertion 来复用测试模板代码 + +在某种场合下,一些特定的测试代码可以应用在不同的对象上。 + +比如,假设有一个叫 `Edible` 的协议。当一只海豚吃了标识为 `Edible` 的食物时,它会变得高兴。`Mackerel` 和 `Cod` 都遵循 `Edible` 协议。这个时候,Quick 的 shared example(共享用例)能帮你更容易地测试 `Mackerel` 和 `Cod` 的行为。 + +下面的例子为一些 `Edible` 的食物定义了一组共享用例,以测试 mackerel 和 cod 的行为。 + +```swift +// Swift + +import Quick +import Nimble + +class EdibleSharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in + it("makes dolphins happy") { + let dolphin = Dolphin(happy: false) + let edible = sharedExampleContext()["edible"] + dolphin.eat(edible) + expect(dolphin.isHappy).to(beTruthy()) + } + } + } +} + +class MackerelSpec: QuickSpec { + override func spec() { + var mackerel: Mackerel! + beforeEach { + mackerel = Mackerel() + } + + itBehavesLike("something edible") { ["edible": mackerel] } + } +} + +class CodSpec: QuickSpec { + override func spec() { + var cod: Cod! + beforeEach { + cod = Cod() + } + + itBehavesLike("something edible") { ["edible": cod] } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; + +QuickConfigurationBegin(EdibleSharedExamplesConfiguration) + ++ (void)configure:(Configuration *configuration) { + sharedExamples(@"something edible", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"makes dolphins happy") { + Dolphin *dolphin = [[Dolphin alloc] init]; + dolphin.happy = NO; + id edible = exampleContext()[@"edible"]; + [dolphin eat:edible]; + expect(dolphin.isHappy).to(beTruthy()) + } + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(MackerelSpec) + +__block Mackerel *mackerel = nil; +beforeEach(^{ + mackerel = [[Mackerel alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": mackerel }; }); + +QuickSpecEnd + +QuickSpecBegin(CodSpec) + +__block Mackerel *cod = nil; +beforeEach(^{ + cod = [[Cod alloc] init]; +}); + +itBehavesLike(@"someting edible", ^{ return @{ @"edible": cod }; }); + +QuickSpecEnd +``` + +共享用例可以包括任意数量的 `it`, `context` 和 `describe` 代码块。当使用它们来测试不同对象的相同行为时,你可以少写*很多*不必要的重复代码。 + +一般来说,你使用共享用例进行测试时不需要依赖其他额外的对象。在 Swift 中,你可以简单地用一个不带参数的 `sharedExample` 闭包来使用共享用例。当你需要进行全局测试时,这很有用。 + +```swift +// Swift + +import Quick + +sharedExamples("everything under the sea") { + // ... +} + +itBehavesLike("everything under the sea") +``` +> 如果你使用 Objective-C 的话,你需要传入一个带 `QCKDSLSharedExampleContext` 参数的 block,即使你并不打算使用它。不好意思,你只能这样做,人生有时就是这么的无奈。:cookie: :bomb: + +你也可以使用 `fitBehavesLike` 函数来单独测试共享用例。 diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md new file mode 100644 index 0000000..9e83ead --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md @@ -0,0 +1,131 @@ +# 使用模拟对象进行测试 + +## 测试替身 + +下面的问题在写测试时经常出现。比如:`Car` 依赖于/使用 `Tire` 。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesA.png) + +`CarTests` 用来测试调用了 `Tire` 的 `Car` 。这时候,在 `Tire` 里出现的 bug 会导致 `CarTests` 测试失败(即使 `Car` 是没有错误的)。 + +这时候很难说清楚到底是什么出错了。为了避免这个问题,我们可以使用一个替身对象,来代替 `CarTests` 里面的 `Tire` 。对于这个问题,我们会为 `Tire` 创建一个替身对象,命名为 `PerfectTire` 。 + +![](https://github.com/Quick/Assets/blob/master/Screenshots/TestUsingMock_BusesAmock.png) + +`PerfectTire` 具有和 `Tire` 一样的函数和属性。但是,这些函数和属性的实现可能会有所不同。 + +像 `PerfectTire` 这样的对象叫做“测试替身”。测试替身充当替身对象,用于独立测试多个相关对象的功能。以下是测试替身的几种类型: + +- 模拟对象:用于从测试类中接收输出。 +- 桩对象:用于为测试类提供输入。 +- 伪对象:具有与原来的类相似的行为。 + +我们先了解一下如何使用模拟对象。 + +## 模拟对象 + +模拟对象着眼于说明它与其它对象的正确交互,并且当出现错误时用来检测问题。模拟对象应该事先知道测试时会发生什么,并且该做出怎样的反应。 + +### 在 Swift 中使用模拟对象来写测试 + +#### 应用案例 + +例如,我们有一个应用,它会从互联网上获取数据。 + +* 在 `ViewController` 中展示从互联网上获取的数据。 +* 自定义类,实现 `DataProviderProtocol` ,负责获取数据。 + +`DataProviderProtocol` 如下定义: + +```swift +protocol DataProviderProtocol: class { + func fetch(callback: (data: String) -> Void) +} +``` + +`fetch()` 从互联网上获取数据,并通过闭包 `callback` 返回数据。 + +下面的 `DataProvider` 实现了 `DataProviderProtocol` 协议。 + +```swift +class DataProvider: NSObject, DataProviderProtocol { + func fetch(callback: (data: String) -> Void) { + let url = NSURL(string: "http://example.com/")! + let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) + let task = session.dataTaskWithURL(url, completionHandler: { + (data, resp, err) in + let string = NSString(data:data!, encoding:NSUTF8StringEncoding) as! String + callback(data: string) + }) + task.resume() + } +} +``` + +在我们这个场景里,`ViewController` 的 `viewDidLoad()` 里调用了 `fetch()` 。 + +```swift +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet weak var resultLabel: UILabel! + private var dataProvider: DataProviderProtocol? + + // MARK: View Controller Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + + dataProvider = dataProvider ?? DataProvider() + + dataProvider?.fetch({ [unowned self] (data) -> Void in + self.resultLabel.text = data + }) + } +} +``` + +#### 用 `DataProviderProtocol` 协议的模拟对象进行测试 + +`ViewController` 依赖于 `DataProviderProtocol` 协议。为了测试这个 viewController ,要创建一个遵循 `DataProviderProtocol` 的模拟对象。 + +模拟对象是非常有用的。因为使用它,你可以: + +- 更快地运行测试。 +- 即使未联网也可以进行测试。 +- 对 `ViewController` 进行独立测试。 + +```swift +class MockDataProvider: NSObject, DataProviderProtocol { + var fetchCalled = false + func fetch(callback: (data: String) -> Void) { + fetchCalled = true + callback(data: "foobar") + } +} +``` + +当 `fetch()` 被调用的时候,`fetchCalled` 会被设为 `true` 。这样能使测试代码确认对象是否准备好进行测试。 + +下面的代码验证了当 `ViewController` 加载时,会运行 `dataProvider.fetch()` 。 + +```swift +override func spec() { + describe("view controller") { + it("fetch data with data provider") { + let mockProvier = MockDataProvider() + let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as! ViewController + viewController.dataProvier = mockProvier + + expect(mockProvier.fetchCalled).to(equal(false)) + + let _ = viewController.view + + expect(mockProvier.fetchCalled).to(equal(true)) + } + } +} +``` + +如果你对写测试感兴趣,想学习更多的内容,请参考 https://realm.io/news/testing-in-swift/ 。 + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md new file mode 100644 index 0000000..59f68d8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md @@ -0,0 +1,174 @@ +# 测试 OS X 和 iOS 应用 + +*[在项目中添加测试](SettingUpYourXcodeProject.md)* 这篇文章详细介绍了有关如何测试 Objective-C 和 Swift 的函数和类的内容。 +本文将介绍一些额外的技巧,用来测试**类**,如 `UIViewController` 及其子类。 + +> 你可以参考这个简短的 [Lightning Talk](https://vimeo.com/115671189#t=37m50s)(从37分50秒开始),它涵盖了绝大多数这方面的话题。 + +## 触发 `UIViewController` 生命周期事件 + +通常,当你的视图控制器(view controller)呈现在应用中,UIKit 会自动触发生命周期事件。然而,在测试 `UIViewController` 的时候,你需要自己手动触发这些事件。你可以通过以下任意一种方法来实现它: + +1. 通过访问 `UIViewController.view` 来触发事件,如: `UIViewController.viewDidLoad()` 。 +2. 使用 `UIViewController.beginAppearanceTransition()` 来触发大多数生命周期事件。 +3. 直接调用方法,如:`UIViewController.viewDidLoad()` 或 `UIViewController.viewWillAppear()` 。 + +```swift +// Swift + +import Quick +import Nimble +import BananaApp + +class BananaViewControllerSpec: QuickSpec { + override func spec() { + var viewController: BananaViewController! + beforeEach { + viewController = BananaViewController() + } + + describe(".viewDidLoad()") { + beforeEach { + // Method #1: Access the view to trigger BananaViewController.viewDidLoad(). + let _ = viewController.view + } + + it("sets the banana count label to zero") { + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal("0")) + } + } + + describe("the view") { + beforeEach { + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + viewController.beginAppearanceTransition(true, animated: false) + viewController.endAppearanceTransition() + } + // ... + } + + describe(".viewWillDisappear()") { + beforeEach { + // Method #3: Directly call the lifecycle event. + viewController.viewWillDisappear(false) + } + // ... + } + } +} +``` + +```objc +// Objective-C + +@import Quick; +@import Nimble; +#import "BananaViewController.h" + +QuickSpecBegin(BananaViewControllerSpec) + +__block BananaViewController *viewController = nil; +beforeEach(^{ + viewController = [[BananaViewController alloc] init]; +}); + +describe(@"-viewDidLoad", ^{ + beforeEach(^{ + // Method #1: Access the view to trigger -[BananaViewController viewDidLoad]. + [viewController view]; + }); + + it(@"sets the banana count label to zero", ^{ + // Since the label is only initialized when the view is loaded, this + // would fail if we didn't access the view in the `beforeEach` above. + expect(viewController.bananaCountLabel.text).to(equal(@"0")) + }); +}); + +describe(@"the view", ^{ + beforeEach(^{ + // Method #2: Triggers .viewDidLoad(), .viewWillAppear(), and .viewDidAppear() events. + [viewController beginAppearanceTransition:YES animated:NO]; + [viewController endAppearanceTransition]; + }); + // ... +}); + +describe(@"-viewWillDisappear", ^{ + beforeEach(^{ + // Method #3: Directly call the lifecycle event. + [viewController viewWillDisappear:NO]; + }); + // ... +}); + +QuickSpecEnd +``` + +## 初始化在故事板(Storyboard)中定义的视图控制器 + +为了初始化在故事板中定义的视图控制器,你需要先为它分配一个 **Storyboard ID** : + +![](http://f.cl.ly/items/2X2G381K1h1l2B2Q0g3L/Screen%20Shot%202015-02-27%20at%2011.58.06%20AM.png) + +为视图控制器分配 ID 后,就可以在测试中初始化了: + +```swift +// Swift + +var viewController: BananaViewController! +beforeEach { + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + let storyboard = UIStoryboard(name: "Main", bundle: nil) + // 2. Use the storyboard to instantiate the view controller. + viewController = + storyboard.instantiateViewControllerWithIdentifier( + "BananaViewControllerID") as! BananaViewController +} +``` + +```objc +// Objective-C + +__block BananaViewController *viewController = nil; +beforeEach(^{ + // 1. Instantiate the storyboard. By default, it's name is "Main.storyboard". + // You'll need to use a different string here if the name of your storyboard is different. + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; + // 2. Use the storyboard to instantiate the view controller. + viewController = [storyboard instantiateViewControllerWithIdentifier:@"BananaViewControllerID"]; +}); +``` + +## 触发 UIControl 事件(如:点击按钮) + +按钮以及其他继承自 `UIControl` 的 UIKit 类定义了一些方法,使我们能够通过程序代码发送控制事件,如:点击按钮。 +以下代码演示了如何测试点击按钮触发的行为: + +```swift +// Swift + +describe("the 'more bananas' button") { + it("increments the banana count label when tapped") { + viewController.moreButton.sendActionsForControlEvents( + UIControlEvents.TouchUpInside) + expect(viewController.bananaCountLabel.text).to(equal("1")) + } +} +``` + +```objc +// Objective-C + +describe(@"the 'more bananas' button", ^{ + it(@"increments the banana count label when tapped", ^{ + [viewController.moreButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + expect(viewController.bananaCountLabel.text).to(equal(@"1")); + }); +}); +``` + + diff --git a/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md b/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md new file mode 100644 index 0000000..c89e25e --- /dev/null +++ b/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md @@ -0,0 +1,10 @@ +# 常见的安装问题 + +这里有一些解决方案,用来处理使用框架时遇到的一些问题。 + +## No such module 'Quick' + +- 如果你已经运行了 `pod install` ,那么关闭并重新打开 Xcode workspace 。如果这样做还没解决问题,那么请接着进行下面的步骤。 +- 删除 `~/Library/Developer/Xcode/DerivedData` **整个**目录,这里面包含了 `ModuleCache` 。 +- 在 Manage Schemes 对话框中,勾选 `Quick` 、`Nimble` 、`Pods-ProjectnameTests` ,然后重新编译它们(`Cmd+B`)。 + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ +- [ ] I have read [CONTRIBUTING](https://github.com/Quick/Nimble/blob/master/CONTRIBUTING.md) and have done my best to follow them. + +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +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`.) + +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) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +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? + +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)? + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore b/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore new file mode 100644 index 0000000..6930efd --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore @@ -0,0 +1,29 @@ +.DS_Store +**/xcuserdata/* +**/*.xccheckout +**/*.xcscmblueprint +build/ +.idea +DerivedData/ +Nimble.framework.zip + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts +Carthage/Checkouts/**/*.* +Carthage/Checkouts/**/Cart* +Carthage/Checkouts/**/Tests +!Carthage/Checkouts/**/LICENSE.* +!Carthage/Checkouts/**/*.md +!Carthage/Checkouts/**/*.swift +!Carthage/Checkouts/**/*.h +!Carthage/Checkouts/**/*.m +!Carthage/Checkouts/**/*.c +Carthage/Build + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml b/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version b/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml b/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml new file mode 100644 index 0000000..cb105e7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml @@ -0,0 +1,19 @@ +disabled_rules: + - todo + - variable_name + - force_try + - force_cast + +included: + - Sources + - Tests + +excluded: + - Carthage/Checkouts + +trailing_comma: + mandatory_comma: true + +line_length: + ignores_comments: true + ignores_function_declarations: true diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml b/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml new file mode 100644 index 0000000..23ce159 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml @@ -0,0 +1,51 @@ +osx_image: xcode8.3 +language: generic +matrix: + include: + - os: osx + sudo: required + env: TYPE=podspec + - os: osx + env: TYPE=ios NIMBLE_RUNTIME_IOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=tvos NIMBLE_RUNTIME_TVOS_SDK_VERSION=10.0 + - os: osx + env: TYPE=macos + - os: osx + env: TYPE=macos + osx_image: xcode9 + - os: osx + env: TYPE=macos + osx_image: xcode9.1 + - os: osx + env: TYPE=macos + osx_image: xcode9.2 + - os: osx + env: TYPE=macos + osx_image: xcode9.3 + - os: osx + env: TYPE=macos + osx_image: xcode9.4 + - os: osx + env: TYPE=swiftpm + - os: osx + env: TYPE=swiftpm + osx_image: xcode9 + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + - os: linux + dist: trusty + sudo: required + env: + - TYPE=swiftpm + - SWIFT_VERSION=4.0.2 + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" +install: + - if [[ "$TYPE" == "podspec" ]]; then sudo gem install bundler; bundle install; fi +script: + - ./test $TYPE diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md @@ -0,0 +1,120 @@ + + + +- [Welcome to Nimble!](#welcome-to-nimble!) + - [Reporting Bugs](#reporting-bugs) + - [Building the Project](#building-the-project) + - [Pull Requests](#pull-requests) + - [Style Conventions](#style-conventions) + - [Core Members](#core-members) + - [Code of Conduct](#code-of-conduct) + + + +# Welcome to Nimble! + +We're building a testing framework for a new generation of Swift and +Objective-C developers. + +Nimble should be easy to use and easy to maintain. Let's keep things +simple and well-tested. + +**tl;dr:** If you've added a file to the project, make sure it's +included in both the OS X and iOS targets. + +## Reporting Bugs + +Nothing is off-limits. If you're having a problem, we want to hear about +it. + +- See a crash? File an issue. +- Code isn't compiling, but you don't know why? Sounds like you should + submit a new issue, bud. +- Went to the kitchen, only to forget why you went in the first place? + Better submit an issue. + +Be sure to include in your issue: + +- Your Xcode version (eg - Xcode 7.0.1 7A1001) +- Your version of Nimble (eg - v2.0.0 or git sha `20a3f3b4e63cc8d97c92c4164bf36f2a2c9a6e1b`) +- What are the steps to reproduce this issue? +- What platform are you using? (eg - OS X, iOS, watchOS, tvOS) +- If the problem is on a UI Testing Bundle, Unit Testing Bundle, or some other target configuration +- Are you using carthage or cocoapods? + +## Building the Project + +- Use `Nimble.xcodeproj` to work on Nimble. + +## Running the Swift Package Manager tests + +1. Install `swiftenv` by running a line from the build script (`.travis.yml`): + + eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" + +2. Run `./test swiftpm` + +## Pull Requests + +- Nothing is trivial. Submit pull requests for anything: typos, + whitespace, you name it. +- Not all pull requests will be merged, but all will be acknowledged. If + no one has provided feedback on your request, ping one of the owners + by name. +- Make sure your pull request includes any necessary updates to the + README or other documentation. +- Be sure the unit tests for both the OS X and iOS targets of Nimble + before submitting your pull request. You can run all the OS X & iOS unit + tests using `./test`. +- If you've added a file to the project, make sure it's included in both + the OS X and iOS targets. +- The `master` branch will always support the stable Xcode version. Other + branches will point to their corresponding versions they support. +- If you're making a configuration change, make sure to edit both the xcode + project and the podspec file. + +### Style Conventions + +- Indent using 4 spaces. +- Keep lines 100 characters or shorter. Break long statements into + shorter ones over multiple lines. +- In Objective-C, use `#pragma mark -` to mark public, internal, + protocol, and superclass methods. + +## Core Members + +If a few of your pull requests have been merged, and you'd like a +controlling stake in the project, file an issue asking for write access +to the repository. + +### Code of Conduct + +Your conduct as a core member is your own responsibility, but here are +some "ground rules": + +- Feel free to push whatever you want to master, and (if you have + ownership permissions) to create any repositories you'd like. + + Ideally, however, all changes should be submitted as GitHub pull + requests. No one should merge their own pull request, unless no + other core members respond for at least a few days. + + If you'd like to create a new repository, it'd be nice if you created + a GitHub issue and gathered some feedback first. + +- It'd be awesome if you could review, provide feedback on, and close + issues or pull requests submitted to the project. Please provide kind, + constructive feedback. Please don't be sarcastic or snarky. + +### Creating a Release + +The process is relatively straight forward, but here's is a useful checklist for tagging: + +- Look at changes from the previously tagged release and write release notes: `git log v0.4.0...HEAD` +- Run the release script: `./script/release A.B.C release-notes-file` +- The script will prompt you to create a new [GitHub release](https://github.com/Quick/Nimble/releases). + - Use the same release notes you created for the tag, but tweak up formatting for GitHub. +- Update [Quick](https://github.com/Quick/Quick) + - Update Quick's submodule reference to the newly released Nimble version + - Update Nimble version in `README.md` and Documentation in [Quick](https://github.com/Quick/Quick) if it's not a patch version update. +- Announce! diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private b/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private new file mode 100644 index 0000000..23d7e11 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.private @@ -0,0 +1 @@ +github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved b/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved new file mode 100644 index 0000000..32a1c25 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Cartfile.resolved @@ -0,0 +1,2 @@ +github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923" +github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt new file mode 100644 index 0000000..ca8f5b8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift new file mode 100644 index 0000000..c1e2ed8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Package.swift @@ -0,0 +1,9 @@ +import PackageDescription + +let package = Package( + name: "CwlCatchException", + targets: [ + Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]), + Target(name: "CwlCatchExceptionSupport") + ] +) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md new file mode 100644 index 0000000..0f97b03 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/README.md @@ -0,0 +1,46 @@ +# 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. + +## 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), + +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" diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..3e89e23 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,35 @@ +// +// CwlCatchException.swift +// CwlAssertionTesting +// +// 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 + +#if SWIFT_PACKAGE +import CwlCatchExceptionSupport +#endif + +private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { + return catchExceptionOfKind(type, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + return catchReturnTypeConverter(self, block: block) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m new file mode 100644 index 0000000..8cf414f --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m @@ -0,0 +1,37 @@ +// +// CwlCatchException.m +// CwlAssertionTesting +// +// 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 "CwlCatchException.h" + +#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +__attribute__((visibility("hidden"))) +#endif +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h new file mode 100644 index 0000000..0c8dd87 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h @@ -0,0 +1,32 @@ +// +// CwlCatchException.h +// CwlCatchException +// +// 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 + +//! 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)); diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt new file mode 100644 index 0000000..693a2fe --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/LICENSE.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright © 2017 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. diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift new file mode 100644 index 0000000..8792aac --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Package.swift @@ -0,0 +1,19 @@ +import PackageDescription + +let package = Package( + name: "CwlPreconditionTesting", + targets: [ + Target(name: "CwlPreconditionTesting", dependencies: [ + "CwlMachBadInstructionHandler" + ]), + Target(name: "CwlMachBadInstructionHandler") + ], + dependencies: [ + .Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])), + ], + exclude: [ + "Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + "Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + ] +) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a42a5b5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/README.md @@ -0,0 +1,73 @@ +# CwlPreconditionTesting + +A Mach exception handler, written in Swift and Objective-C, that allows `EXC_BAD_INSTRUCTION` (as raised by Swift's `assertionFailure`/`preconditionFailure`/`fatalError`) to be caught and tested. + +NOTE: the iOS code runs in the simulator *only*. It is for logic testing and cannot be deployed to the device due to the Mach exception API being private on iOS. + +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) + +## 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), + +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/CwlPreconditionTesting.git", majorVersion: 1) + +### CocoaPods + +Add the following lines to your target in your "Podfile": + + pod 'CwlPreconditionTesting', :git => 'https://github.com/mattgallagher/CwlPreconditionTesting.git' + pod 'CwlCatchException', :git => 'https://github.com/mattgallagher/CwlCatchException.git' + +### Carthage + +Add the following line to your Cartfile: + + git "https://github.com/mattgallagher/CwlPreconditionTesting.git" "master" + +## 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) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m new file mode 100644 index 0000000..8183196 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m @@ -0,0 +1,50 @@ +// +// CwlMachBadExceptionHandler.m +// 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. +// + +#if defined(__x86_64__) + + #import "mach_excServer.h" + #import "CwlMachBadInstructionHandler.h" + + @protocol BadInstructionReply + +(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 diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h new file mode 100644 index 0000000..aef59c2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -0,0 +1,70 @@ +// +// CwlMachBadInstructionHandler.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 +#import + +NS_ASSUME_NONNULL_BEGIN + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; +} request_mach_exception_raise_t; + +// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; +} reply_mach_exception_raise_state_t; + +typedef struct +{ + mach_port_t exception_port; + exception_type_t exception; + mach_exception_data_type_t const * _Nullable code; + mach_msg_type_number_t codeCnt; + int32_t * _Nullable flavor; + natural_t const * _Nullable old_state; + mach_msg_type_number_t old_stateCnt; + thread_state_t _Nullable new_state; + mach_msg_type_number_t * _Nullable new_stateCnt; +} bad_instruction_exception_reply_t; + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c new file mode 100644 index 0000000..733c564 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Sun Jan 29 19:05:29 2017 + * with a MiG generated by bootstrap_cmds-96.20.2 + * OPTIONS: + */ + +#if defined(__x86_64__) + +/* Module mach_exc */ + +#define __MIG_check__Request__mach_exc_subsystem__ 1 + +#include "mach_excServer.h" + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + + typedef __Request__mach_exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise") + __BeforeRcvRpc(2405, "mach_exception_raise") + +#if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state") + __BeforeRcvRpc(2406, "mach_exception_raise_state") + +#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") + +#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity") +} + + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = { + mach_exc_server_routine, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + OutHeadP->msgh_reserved = 0; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h new file mode 100644 index 0000000..52e53ae --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h @@ -0,0 +1,321 @@ +#ifndef _mach_exc_server_ +#define _mach_exc_server_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +/* BEGIN MIG_STRNCPY_ZEROFILL CODE */ + +#if defined(__has_include) +#if __has_include() +#ifndef USING_MIG_STRNCPY_ZEROFILL +#define USING_MIG_STRNCPY_ZEROFILL +#endif +#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ +#endif /* __has_include() */ +#endif /* __has_include */ + +/* END MIG_STRNCPY_ZEROFILL CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigServerHeader +__BeforeMigServerHeader +#endif /* __BeforeMigServerHeader */ + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +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 +); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +mig_routine_t mach_exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +extern const struct catch_mach_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem; + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + + +/* union of all requests */ + +#ifndef __RequestUnion__catch_mach_exc_subsystem__defined +#define __RequestUnion__catch_mach_exc_subsystem__defined +union __RequestUnion__catch_mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2405 },\ + { "mach_exception_raise_state", 2406 },\ + { "mach_exception_raise_state_identity", 2407 } +#endif + +#ifdef __AfterMigServerHeader +__AfterMigServerHeader +#endif /* __AfterMigServerHeader */ + +#endif /* _mach_exc_server_ */ diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..91e5d4d --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,89 @@ +// +// CwlBadInstructionException.swift +// 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 + +#if SWIFT_PACKAGE + import CwlMachBadInstructionHandler +#endif + +private func raiseBadInstructionException() { + BadInstructionException().raise() +} + +/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type. +@objc(BadInstructionException) +public class BadInstructionException: NSException { + static var name: String = "com.cocoawithlove.BadInstruction" + + init() { + super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// 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 = 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 = 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.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 + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..f96ec63 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,197 @@ +// +// CwlCatchBadInstruction.swift +// 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 + +#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) + } + } + + extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> 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(in block: (UnsafeMutablePointer) -> 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() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil + + static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> 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.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.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 + } + + /// 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) + } + } + + 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 + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift new file mode 100644 index 0000000..eb9bc19 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift @@ -0,0 +1,108 @@ +// +// 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.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 diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..8d99d5e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,55 @@ +// +// CwlDarwinDefinitions.swift +// 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 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.size / MemoryLayout.size) + + public let EXC_TYPES_COUNT = 14 + public struct execTypesCountTuple { + // 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 diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h new file mode 100644 index 0000000..7c50da1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h @@ -0,0 +1,32 @@ +// +// 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 + +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" diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h new file mode 100644 index 0000000..4e28f95 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h @@ -0,0 +1,29 @@ +// +// 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 + +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[]; diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test b/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test new file mode 100644 index 0000000..a995ae2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Dockerfile.test @@ -0,0 +1,3 @@ +FROM swift:latest +COPY . . +CMD ./test swiftpm diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile b/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile new file mode 100644 index 0000000..eca9219 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.5.0' diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock b/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock new file mode 100644 index 0000000..36a0839 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock @@ -0,0 +1,76 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + atomos (0.1.2) + claide (1.0.2) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + minitest (5.11.3) + molinillo (0.6.5) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + ruby-macho (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.5.0) + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE b/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec new file mode 100644 index 0000000..93cbdda --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec @@ -0,0 +1,52 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "7.1.3" + 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. + DESC + 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.osx.deployment_target = "10.10" + s.tvos.deployment_target = "9.0" + s.source = { :git => "https://github.com/Quick/Nimble.git", + :tag => "v#{s.version}" } + + s.source_files = [ + "Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlCatchException/Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/**/*.{swift,h,m,c}", + ] + + s.osx.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.ios.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", + ] + s.tvos.exclude_files = [ + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", + "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", + ] + + s.exclude_files = "Sources/Nimble/Adapters/NonObjectiveC/*.swift" + s.weak_framework = "XCTest" + s.requires_arc = true + s.compiler_flags = '-DPRODUCT_NAME=Nimble/Nimble' + s.pod_target_xcconfig = { + 'APPLICATION_EXTENSION_API_ONLY' => 'YES', + 'ENABLE_BITCODE' => 'NO', + 'OTHER_LDFLAGS' => '$(inherited) -weak-lswiftXCTest -Xlinker -no_application_extension', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0a2224e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2371 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + A8F2B2541E79A4AB005BDD17 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + A8F2B2581E79A4B0005BDD17 /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; }; + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */; }; + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */; }; + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */; }; + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */; }; + 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; }; + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; }; + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F1A74291940169200FFFC47 /* Nimble.framework */; }; + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 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 */; }; + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A56671A3B305F009E1637 /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; }; + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; }; + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */; }; + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; }; + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1341B9E085700C7B8DA /* HaveCount.swift */; }; + 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 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; }; + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; }; + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; }; + 1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */; }; + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */; }; + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */; }; + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + 1F5DF1AA1BDCA10200C3A531 /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; }; + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */; }; + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F91DD301C74BF61002C309F /* BeVoid.swift */; }; + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F925EAD195C0D6300ED456B /* Nimble.framework */; }; + 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F925EE2195C0DFD00ED456B /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; }; + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; }; + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */; }; + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */; }; + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EEE195C136500ED456B /* BeLogicalTest.swift */; }; + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF5195C147800ED456B /* BeCloseToTest.swift */; }; + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EF8195C175000ED456B /* BeNilTest.swift */; }; + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFD195C186800ED456B /* BeginWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFB195C186800ED456B /* BeginWithTest.swift */; }; + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EFE195C187600ED456B /* EndWithTest.swift */; }; + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F01195C189500ED456B /* ContainTest.swift */; }; + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F04195C18B700ED456B /* EqualTest.swift */; }; + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */; }; + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */; }; + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */; }; + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */; }; + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */; }; + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */; }; + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */; }; + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD081968AB07008ED995 /* DSL.swift */; }; + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD091968AB07008ED995 /* Expectation.swift */; }; + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0A1968AB07008ED995 /* Expression.swift */; }; + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */; }; + 1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */; }; + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */; }; + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */; }; + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD101968AB07008ED995 /* BeEmpty.swift */; }; + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD111968AB07008ED995 /* BeginWith.swift */; }; + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */; }; + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD151968AB07008ED995 /* BeLessThan.swift */; }; + 1FD8CD4E1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */; }; + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD171968AB07008ED995 /* BeLogical.swift */; }; + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD181968AB07008ED995 /* BeNil.swift */; }; + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1A1968AB07008ED995 /* Contain.swift */; }; + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1B1968AB07008ED995 /* EndWith.swift */; }; + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; }; + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; }; + 1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; }; + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; }; + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */; }; + 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 */; }; + 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 */; }; + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C41E7F547E00A2F694 /* ToSucceedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */; }; + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0A26221E7F52360092A34E /* ToSucceed.swift */; }; + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */; }; + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */; }; + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */; }; + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */; }; + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */; }; + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */; }; + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; }; + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */; }; + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */; }; + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */; }; + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */; }; + AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4BA9AC1C88DDB500B73906 /* Errors.swift */; }; + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE441C80BF8000B94CD3 /* MatchError.swift */; }; + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; }; + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.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 */; }; + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */; }; + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */; }; + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */; }; + CD79C9A51D2CC848004B6F9A /* ObjCBeginWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */; }; + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */; }; + CD79C9A71D2CC848004B6F9A /* ObjCBeGreaterThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */; }; + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */; }; + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */; }; + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */; }; + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */; }; + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */; }; + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */; }; + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */; }; + CD79C9AF1D2CC848004B6F9A /* ObjCContainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */; }; + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */; }; + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */; }; + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */; }; + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */; }; + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */; }; + 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 */; }; + 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 */; }; + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */; }; + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */; }; + CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */; }; + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; }; + 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, ); }; }; + CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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 */; }; + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */; }; + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB1BC781A92235600F743C3 /* AllPass.swift */; }; + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */; }; + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F5DF1541BDCA0CE00C3A531; + remoteInfo = "Nimble-tvOS"; + }; + 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = "Nimble-iOS"; + }; + 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F1A74281940169200FFFC47; + remoteInfo = Nimble; + }; + 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; + 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F1A74201940169200FFFC47 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F925EAC195C0D6300ED456B; + remoteInfo = "Nimble-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = ""; }; + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTests.swift; sourceTree = ""; }; + 1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = ""; }; + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSL.h; sourceTree = ""; }; + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSL.m; sourceTree = ""; }; + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBExceptionCapture.h; sourceTree = ""; }; + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBExceptionCapture.m; sourceTree = ""; }; + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NMBStringify.h; sourceTree = ""; }; + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NMBStringify.m; sourceTree = ""; }; + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBExpectation.swift; sourceTree = ""; }; + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBObjCMatcher.swift; sourceTree = ""; }; + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionCapture.swift; sourceTree = ""; }; + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMatcherWrapper.swift; sourceTree = ""; }; + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherFunc.swift; sourceTree = ""; }; + 1F1A74291940169200FFFC47 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A742D1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1A742E1940169200FFFC47 /* Nimble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nimble.h; sourceTree = ""; }; + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F1A743A1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAKindOfTest.swift; sourceTree = ""; }; + 1F2752D119445B8400052A26 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = README.md; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.markdown; }; + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmptyTest.swift; sourceTree = ""; }; + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAsyncTest.m; sourceTree = ""; }; + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NimbleSpecHelper.h; sourceTree = ""; }; + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeAnInstanceOfTest.m; sourceTree = ""; }; + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeKindOfTest.m; sourceTree = ""; }; + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeCloseToTest.m; sourceTree = ""; }; + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeginWithTest.m; sourceTree = ""; }; + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanTest.m; sourceTree = ""; }; + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeGreaterThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeIdenticalToTest.m; sourceTree = ""; }; + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanTest.m; sourceTree = ""; }; + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeLessThanOrEqualToTest.m; sourceTree = ""; }; + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTruthyTest.m; sourceTree = ""; }; + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalsyTest.m; sourceTree = ""; }; + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeTrueTest.m; sourceTree = ""; }; + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeFalseTest.m; sourceTree = ""; }; + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeNilTest.m; sourceTree = ""; }; + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainTest.m; sourceTree = ""; }; + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEndWithTest.m; sourceTree = ""; }; + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCEqualTest.m; sourceTree = ""; }; + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCMatchTest.m; sourceTree = ""; }; + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCRaiseExceptionTest.m; sourceTree = ""; }; + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertionTest.swift; sourceTree = ""; }; + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSyncTest.m; sourceTree = ""; }; + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoidTest.swift; sourceTree = ""; }; + 1F91DD301C74BF61002C309F /* BeVoid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeVoid.swift; sourceTree = ""; }; + 1F925EAD195C0D6300ED456B /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NimbleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousTest.swift; sourceTree = ""; }; + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOfTest.swift; sourceTree = ""; }; + 1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaisesExceptionTest.swift; sourceTree = ""; }; + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLogicalTest.swift; sourceTree = ""; }; + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseToTest.swift; sourceTree = ""; }; + 1F925EF8195C175000ED456B /* BeNilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeNilTest.swift; sourceTree = ""; }; + 1F925EFB195C186800ED456B /* BeginWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeginWithTest.swift; sourceTree = ""; }; + 1F925EFE195C187600ED456B /* EndWithTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWithTest.swift; sourceTree = ""; }; + 1F925F01195C189500ED456B /* ContainTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainTest.swift; sourceTree = ""; }; + 1F925F04195C18B700ED456B /* EqualTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EqualTest.swift; sourceTree = ""; }; + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanTest.swift; sourceTree = ""; }; + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanTest.swift; sourceTree = ""; }; + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanOrEqualToTest.swift; sourceTree = ""; }; + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanOrEqualToTest.swift; sourceTree = ""; }; + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeEmptyTest.m; sourceTree = ""; }; + 1FA0C3FE1E30B14500623165 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToTest.swift; sourceTree = ""; }; + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleEnvironment.swift; sourceTree = ""; }; + 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotificationTest.swift; sourceTree = ""; }; + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotification.swift; sourceTree = ""; }; + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionRecorder.swift; sourceTree = ""; }; + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdapterProtocols.swift; sourceTree = ""; }; + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleXCTestHandler.swift; sourceTree = ""; }; + 1FD8CD081968AB07008ED995 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + 1FD8CD091968AB07008ED995 /* Expectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expectation.swift; sourceTree = ""; }; + 1FD8CD0A1968AB07008ED995 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailureMessage.swift; sourceTree = ""; }; + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeAnInstanceOf.swift; sourceTree = ""; }; + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeAKindOf.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeCloseTo.swift; sourceTree = ""; }; + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeEmpty.swift; sourceTree = ""; }; + 1FD8CD111968AB07008ED995 /* BeginWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeginWith.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeGreaterThanOrEqualTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeIdenticalTo.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThan.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLessThanOrEqual.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD171968AB07008ED995 /* BeLogical.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeLogical.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD181968AB07008ED995 /* BeNil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BeNil.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1A1968AB07008ED995 /* Contain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Contain.swift; sourceTree = ""; }; + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndWith.swift; sourceTree = ""; }; + 1FD8CD1C1968AB07008ED995 /* Equal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Equal.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = ""; }; + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = ""; }; + 1FD8CD261968AB07008ED995 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = ""; }; + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = ""; }; + 1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = ""; }; + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionDispatcher.swift; sourceTree = ""; }; + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpectationMessage.swift; sourceTree = ""; }; + 29EA59621B551ED2002D767E /* ThrowErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowErrorTest.swift; sourceTree = ""; }; + 29EA59651B551EE6002D767E /* ThrowError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowError.swift; sourceTree = ""; }; + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestCaseProvider.swift; sourceTree = ""; }; + 472FD1341B9E085700C7B8DA /* HaveCount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCount.swift; sourceTree = ""; }; + 472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HaveCountTest.swift; sourceTree = ""; }; + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCountTest.m; sourceTree = ""; }; + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = ""; }; + 7A0A26221E7F52360092A34E /* ToSucceed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceed.swift; sourceTree = ""; }; + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToSucceedTest.swift; sourceTree = ""; }; + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfying.swift; sourceTree = ""; }; + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfyingTest.m; sourceTree = ""; }; + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfyingTest.swift; sourceTree = ""; }; + 7B5358B91C3846C900A23FAA /* SatisfyAnyOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOfTest.swift; sourceTree = ""; }; + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAnyOf.swift; sourceTree = ""; }; + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAnyOfTest.m; sourceTree = ""; }; + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcStringersTest.m; sourceTree = ""; }; + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThrowAssertion.swift; sourceTree = ""; }; + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCUserDescriptionTest.m; sourceTree = ""; }; + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDescriptionTest.swift; sourceTree = ""; }; + A8A3B6E920712FC100E25A08 /* SatisfyAllOfTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SatisfyAllOfTest.swift; sourceTree = ""; }; + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCSatisfyAllOfTest.m; sourceTree = ""; }; + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatisfyAllOf.swift; sourceTree = ""; }; + AE4BA9AC1C88DDB500B73906 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchError.swift; sourceTree = ""; }; + AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = ""; }; + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = ""; }; + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = ""; }; + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = ""; }; + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = ""; }; + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_excServer.h; sourceTree = ""; }; + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DSL+Wait.swift"; sourceTree = ""; }; + DD72EC631A93874A002F7651 /* AllPassTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPassTest.swift; sourceTree = ""; }; + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToObjectTest.swift; sourceTree = ""; }; + DDB1BC781A92235600F743C3 /* AllPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllPass.swift; sourceTree = ""; }; + DDB4D5EC19FE43C200E9D9FE /* Match.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Match.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchTest.swift; sourceTree = ""; }; + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCAllPassTest.m; sourceTree = ""; }; + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+Register.m"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F1A74251940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74311940169200FFFC47 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1A74351940169200FFFC47 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF15F1BDCA0CE00C3A531 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA9195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB4195C0D6300ED456B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F925EB8195C0D6300ED456B /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F14FB61194180A7009F2A08 /* Helpers */ = { + isa = PBXGroup; + children = ( + 1F14FB63194180C5009F2A08 /* utils.swift */, + 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */, + 347155C91C337C8900549F03 /* XCTestCaseProvider.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871BC1CA89EDB00A34BF2 /* DSL.h */, + 1F1871BD1CA89EDB00A34BF2 /* DSL.m */, + 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */, + 1F1871BF1CA89EDB00A34BF2 /* NMBExceptionCapture.m */, + 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */, + 1F1871C11CA89EDB00A34BF2 /* NMBStringify.m */, + F8A1BE2B1CB3710900031679 /* XCTestObservationCenter+Register.m */, + ); + name = NimbleObjectiveC; + path = Sources/NimbleObjectiveC; + sourceTree = ""; + }; + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */ = { + isa = PBXGroup; + children = ( + 1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */, + ); + path = NonObjectiveC; + sourceTree = ""; + }; + 1F1A741F1940169200FFFC47 = { + isa = PBXGroup; + children = ( + 1F2752D119445B8400052A26 /* README.md */, + 1F1A742B1940169200FFFC47 /* Nimble */, + 1F1871B91CA89E1B00A34BF2 /* NimbleObjectiveC */, + 1F1A74381940169200FFFC47 /* NimbleTests */, + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */, + 1F1A742A1940169200FFFC47 /* Products */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + usesTabs = 0; + }; + 1F1A742A1940169200FFFC47 /* Products */ = { + isa = PBXGroup; + children = ( + 1F1A74291940169200FFFC47 /* Nimble.framework */, + 1F1A74341940169200FFFC47 /* NimbleTests.xctest */, + 1F925EAD195C0D6300ED456B /* Nimble.framework */, + 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */, + 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */, + 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 1F1A742B1940169200FFFC47 /* Nimble */ = { + isa = PBXGroup; + children = ( + 1FD8CD041968AB07008ED995 /* Adapters */, + 1FD8CD081968AB07008ED995 /* DSL.swift */, + DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */, + 1FD8CD091968AB07008ED995 /* Expectation.swift */, + 1FD8CD0A1968AB07008ED995 /* Expression.swift */, + 1FE661561E6574E20035F243 /* ExpectationMessage.swift */, + 1FD8CD0B1968AB07008ED995 /* FailureMessage.swift */, + 1F1A742D1940169200FFFC47 /* Info.plist */, + 1FD8CD0C1968AB07008ED995 /* Matchers */, + 1F1A742E1940169200FFFC47 /* Nimble.h */, + 1FD8CD241968AB07008ED995 /* Utils */, + ); + name = Nimble; + path = Sources/Nimble; + sourceTree = ""; + }; + 1F1A74381940169200FFFC47 /* NimbleTests */ = { + isa = PBXGroup; + children = ( + 1F925EE5195C121200ED456B /* AsynchronousTest.swift */, + 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */, + 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */, + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */, + 1FFD729A1963FC8200CD29A2 /* objc */, + 1F14FB61194180A7009F2A08 /* Helpers */, + 1F925EE3195C11B000ED456B /* Matchers */, + 1F1A74391940169200FFFC47 /* Supporting Files */, + ); + name = NimbleTests; + path = Tests/NimbleTests; + sourceTree = ""; + }; + 1F1A74391940169200FFFC47 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 1F1A743A1940169200FFFC47 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1F925EE3195C11B000ED456B /* Matchers */ = { + isa = PBXGroup; + children = ( + DD72EC631A93874A002F7651 /* AllPassTest.swift */, + 1F1B5AD31963E13900CA8BF9 /* BeAKindOfTest.swift */, + 1F925EE8195C124400ED456B /* BeAnInstanceOfTest.swift */, + 1F925EF5195C147800ED456B /* BeCloseToTest.swift */, + 1F299EAA19627B2D002641AF /* BeEmptyTest.swift */, + 1F925EFB195C186800ED456B /* BeginWithTest.swift */, + 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */, + 1F925F07195C18CF00ED456B /* BeGreaterThanTest.swift */, + DD9A9A8D19CF413800706F49 /* BeIdenticalToObjectTest.swift */, + 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */, + 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */, + 1F925F0A195C18E100ED456B /* BeLessThanTest.swift */, + 1F925EEE195C136500ED456B /* BeLogicalTest.swift */, + 1F925EF8195C175000ED456B /* BeNilTest.swift */, + 1F91DD2C1C74BF36002C309F /* BeVoidTest.swift */, + 7B13BA091DD360DE00C9098C /* ContainElementSatisfyingTest.swift */, + 1F925F01195C189500ED456B /* ContainTest.swift */, + 1F925EFE195C187600ED456B /* EndWithTest.swift */, + 1F925F04195C18B700ED456B /* EqualTest.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 */, + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.swift */, + 7A6AB2C11E7F547E00A2F694 /* ToSucceedTest.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD041968AB07008ED995 /* Adapters */ = { + isa = PBXGroup; + children = ( + 1FD8CD061968AB07008ED995 /* AdapterProtocols.swift */, + 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */, + 1FD8CD051968AB07008ED995 /* AssertionRecorder.swift */, + 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */, + 1FD8CD071968AB07008ED995 /* NimbleXCTestHandler.swift */, + 1F1871BA1CA89E2500A34BF2 /* NonObjectiveC */, + 1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */, + 1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */, + ); + path = Adapters; + sourceTree = ""; + }; + 1FD8CD0C1968AB07008ED995 /* Matchers */ = { + isa = PBXGroup; + children = ( + DDB1BC781A92235600F743C3 /* AllPass.swift */, + 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */, + 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */, + 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */, + 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */, + 1FD8CD101968AB07008ED995 /* BeEmpty.swift */, + 1FD8CD111968AB07008ED995 /* BeginWith.swift */, + 1FD8CD121968AB07008ED995 /* BeGreaterThan.swift */, + 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */, + 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */, + 1FD8CD151968AB07008ED995 /* BeLessThan.swift */, + 1FD8CD161968AB07008ED995 /* BeLessThanOrEqual.swift */, + 1FD8CD171968AB07008ED995 /* BeLogical.swift */, + 1FD8CD181968AB07008ED995 /* BeNil.swift */, + 1F91DD301C74BF61002C309F /* BeVoid.swift */, + 1FD8CD1A1968AB07008ED995 /* Contain.swift */, + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */, + 1FD8CD1B1968AB07008ED995 /* EndWith.swift */, + 1FD8CD1C1968AB07008ED995 /* Equal.swift */, + 472FD1341B9E085700C7B8DA /* HaveCount.swift */, + DDB4D5EC19FE43C200E9D9FE /* Match.swift */, + 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */, + 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */, + AE7ADE441C80BF8000B94CD3 /* MatchError.swift */, + 1FCF91521C61C8A400B15DCB /* PostNotification.swift */, + 1FA0C3FE1E30B14500623165 /* Predicate.swift */, + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, + A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */, + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */, + 29EA59651B551EE6002D767E /* ThrowError.swift */, + 7A0A26221E7F52360092A34E /* ToSucceed.swift */, + ); + path = Matchers; + sourceTree = ""; + }; + 1FD8CD241968AB07008ED995 /* Utils */ = { + isa = PBXGroup; + children = ( + 1FD8CD251968AB07008ED995 /* Functional.swift */, + 1FD8CD261968AB07008ED995 /* Async.swift */, + 1FD8CD271968AB07008ED995 /* SourceLocation.swift */, + 1FD8CD281968AB07008ED995 /* Stringers.swift */, + AE4BA9AC1C88DDB500B73906 /* Errors.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 1FFD729A1963FC8200CD29A2 /* objc */ = { + isa = PBXGroup; + children = ( + 1F4A56681A3B3074009E1637 /* NimbleSpecHelper.h */, + 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */, + 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */, + 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */, + 1F4A566F1A3B319F009E1637 /* ObjCBeCloseToTest.m */, + 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */, + 1F4A568D1A3B342B009E1637 /* ObjCBeFalseTest.m */, + 1F4A56871A3B33CB009E1637 /* ObjCBeFalsyTest.m */, + 1F4A56721A3B3210009E1637 /* ObjCBeginWithTest.m */, + 1F4A56781A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m */, + 1F4A56751A3B3253009E1637 /* ObjCBeGreaterThanTest.m */, + 1F4A567B1A3B3311009E1637 /* ObjCBeIdenticalToTest.m */, + 1F4A566C1A3B3159009E1637 /* ObjCBeKindOfTest.m */, + 1F4A56811A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m */, + 1F4A567E1A3B333F009E1637 /* ObjCBeLessThanTest.m */, + 1F4A56901A3B344A009E1637 /* ObjCBeNilTest.m */, + 1F4A568A1A3B3407009E1637 /* ObjCBeTrueTest.m */, + 1F4A56841A3B33A0009E1637 /* ObjCBeTruthyTest.m */, + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfyingTest.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCountTest.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + A8A3B7052073688A00E25A08 /* ObjCSatisfyAllOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = { + isa = PBXGroup; + children = ( + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */, + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */, + ); + name = "Carthage-Checkouts"; + path = Carthage/Checkouts; + sourceTree = ""; + }; + CDFB69551F7E076F00AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */, + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */, + ); + name = CwlCatchException; + path = CwlCatchException/Sources; + sourceTree = ""; + }; + CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */, + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */, + ); + name = CwlPreconditionTesting; + path = CwlPreconditionTesting/Sources; + sourceTree = ""; + }; + CDFB6A1D1F7E07C600AD8CC7 /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */, + ); + path = CwlCatchException; + sourceTree = ""; + }; + CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */ = { + isa = PBXGroup; + children = ( + CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */, + CDFB6A211F7E07C600AD8CC7 /* include */, + ); + path = CwlCatchExceptionSupport; + sourceTree = ""; + }; + CDFB6A211F7E07C600AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */, + ); + path = include; + sourceTree = ""; + }; + CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */, + CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */, + CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */, + CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */, + CDFB6A2F1F7E082400AD8CC7 /* Mach */, + CDFB6A311F7E082400AD8CC7 /* Posix */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; + CDFB6A2F1F7E082400AD8CC7 /* Mach */ = { + isa = PBXGroup; + children = ( + CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */, + ); + path = Mach; + sourceTree = ""; + }; + CDFB6A311F7E082400AD8CC7 /* Posix */ = { + isa = PBXGroup; + children = ( + CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */, + ); + path = Posix; + sourceTree = ""; + }; + CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = { + isa = PBXGroup; + children = ( + CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */, + CDFB6A351F7E082400AD8CC7 /* include */, + CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */, + CDFB6A381F7E082400AD8CC7 /* mach_excServer.h */, + ); + path = CwlMachBadInstructionHandler; + sourceTree = ""; + }; + CDFB6A351F7E082400AD8CC7 /* include */ = { + isa = PBXGroup; + children = ( + CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */, + ); + path = include; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + 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 */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + 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; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F1A74281940169200FFFC47 /* Nimble-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */; + buildPhases = ( + 1F1A74241940169200FFFC47 /* Sources */, + 1F1A74251940169200FFFC47 /* Frameworks */, + 1F1A74261940169200FFFC47 /* Headers */, + 1F1A74271940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-iOS"; + productName = "Nimble-iOS"; + productReference = 1F1A74291940169200FFFC47 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */; + buildPhases = ( + 1F1A74301940169200FFFC47 /* Sources */, + 1F1A74311940169200FFFC47 /* Frameworks */, + 1F1A74321940169200FFFC47 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F1A74371940169200FFFC47 /* PBXTargetDependency */, + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */, + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */, + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */, + ); + name = "Nimble-iOSTests"; + productName = "Nimble-iOSTests"; + productReference = 1F1A74341940169200FFFC47 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */; + buildPhases = ( + 1F5DF1501BDCA0CE00C3A531 /* Sources */, + 1F5DF1511BDCA0CE00C3A531 /* Frameworks */, + 1F5DF1521BDCA0CE00C3A531 /* Headers */, + 1F5DF1531BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-tvOS"; + productName = "Nimble-tvOS"; + productReference = 1F5DF1551BDCA0CE00C3A531 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */; + buildPhases = ( + 1F5DF15A1BDCA0CE00C3A531 /* Sources */, + 1F5DF15B1BDCA0CE00C3A531 /* Frameworks */, + 1F5DF15C1BDCA0CE00C3A531 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */, + ); + name = "Nimble-tvOSTests"; + productName = "Nimble-tvOSTests"; + productReference = 1F5DF15E1BDCA0CE00C3A531 /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F925EAC195C0D6300ED456B /* Nimble-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */; + buildPhases = ( + 1F925EA8195C0D6300ED456B /* Sources */, + 1F925EA9195C0D6300ED456B /* Frameworks */, + 1F925EAA195C0D6300ED456B /* Headers */, + 1F925EAB195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Nimble-macOS"; + productName = "Nimble-macOS"; + productReference = 1F925EAD195C0D6300ED456B /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */; + buildPhases = ( + 1F925EB3195C0D6300ED456B /* Sources */, + 1F925EB4195C0D6300ED456B /* Frameworks */, + 1F925EB5195C0D6300ED456B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */, + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */, + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */, + ); + name = "Nimble-macOSTests"; + productName = "Nimble-OSXTests"; + productReference = 1F925EB7195C0D6300ED456B /* NimbleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1F1A74201940169200FFFC47 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0900; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + TestTargetID = 1F925EAC195C0D6300ED456B; + }; + A8F2B2541E79A4AB005BDD17 = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1F1A741F1940169200FFFC47; + productRefGroup = 1F1A742A1940169200FFFC47 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1F925EAC195C0D6300ED456B /* Nimble-macOS */, + 1F925EB6195C0D6300ED456B /* Nimble-macOSTests */, + 1F1A74281940169200FFFC47 /* Nimble-iOS */, + 1F1A74331940169200FFFC47 /* Nimble-iOSTests */, + 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */, + 1F5DF15D1BDCA0CE00C3A531 /* Nimble-tvOSTests */, + A8F2B2541E79A4AB005BDD17 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F1A74271940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74321940169200FFFC47 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1531BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15C1BDCA0CE00C3A531 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAB195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB5195C0D6300ED456B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A8F2B2581E79A4B0005BDD17 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F1A74241940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */, + 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 */, + 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */, + 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC791A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3E1968AB07008ED995 /* BeAKindOf.swift in Sources */, + DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */, + 1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */, + 7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */, + 1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 29EA59661B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5A1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4C1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1F1871CC1CA89EDB00A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD461968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE2F1CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */, + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */, + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */, + CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */, + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */, + A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A3A1F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A261F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, + CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, + 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */, + 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F1A74301940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569A1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EEC195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925EFF195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD41963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0E195C18F500ED456B /* BeLessThanOrEqualToTest.swift in Sources */, + 1F4A56661A3B305F009E1637 /* ObjCAsyncTest.m in Sources */, + 1F925EFC195C186800ED456B /* BeginWithTest.swift in Sources */, + 1F14FB64194180C5009F2A08 /* utils.swift in Sources */, + DDB4D5F019FE442800E9D9FE /* MatchTest.swift in Sources */, + 1F4A56731A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */, + 1F4A56821A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 7B13BA0E1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F02195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FC2073644600E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56881A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568E1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F11195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EEF195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A01A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6F92073643000E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0B195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2D1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56761A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EF9195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C31E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B707207368F000E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56701A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56971A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567C1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0C1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF914F1C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D091B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F6207329DD00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568B1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB41A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A567F1A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE6195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BA1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F05195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566D1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569D1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EE9195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59631B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0A1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566A1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13B1B9E0CFE00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1501BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F5DF1791BDCA0F500C3A531 /* BeCloseTo.swift in Sources */, + 1F5DF16C1BDCA0F500C3A531 /* AssertionRecorder.swift in Sources */, + 1F1871D71CA89EEF00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */, + A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */, + 1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */, + 1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */, + 1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */, + AE4BA9AF1C88DDB500B73906 /* Errors.swift in Sources */, + 1F5DF1861BDCA0F500C3A531 /* HaveCount.swift in Sources */, + 1F5DF1811BDCA0F500C3A531 /* BeLogical.swift in Sources */, + 1F1871DB1CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */, + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */, + 1F5DF17C1BDCA0F500C3A531 /* BeGreaterThan.swift in Sources */, + 1F91DD331C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91551C61C8A400B15DCB /* PostNotification.swift in Sources */, + 1F5DF1831BDCA0F500C3A531 /* Contain.swift in Sources */, + 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */, + 1F1871DC1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */, + 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */, + 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */, + 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */, + AE7ADE471C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AC1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */, + 1F5DF16D1BDCA0F500C3A531 /* AdapterProtocols.swift in Sources */, + 1F5DF17B1BDCA0F500C3A531 /* BeginWith.swift in Sources */, + 1F5DF17E1BDCA0F500C3A531 /* BeIdenticalTo.swift in Sources */, + 1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */, + 1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */, + CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */, + 1F5DF18C1BDCA0F500C3A531 /* Async.swift in Sources */, + 1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */, + 1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */, + 1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */, + 964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */, + 1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */, + 1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */, + CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, + 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, + 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, + 1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */, + 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF15A1BDCA0CE00C3A531 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD79C9AD1D2CC848004B6F9A /* ObjCBeTrueTest.m in Sources */, + CD79C9B41D2CC848004B6F9A /* ObjCRaiseExceptionTest.m in Sources */, + 1F5DF1A31BDCA10200C3A531 /* BeLogicalTest.swift in Sources */, + 1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */, + CD79C9B01D2CC848004B6F9A /* ObjCEndWithTest.m in Sources */, + CD79C9B21D2CC848004B6F9A /* ObjCHaveCountTest.m in Sources */, + CD79C9A41D2CC848004B6F9A /* ObjCBeFalsyTest.m in Sources */, + 1F5DF1981BDCA10200C3A531 /* BeAKindOfTest.swift in Sources */, + 1F5DF19B1BDCA10200C3A531 /* BeEmptyTest.swift in Sources */, + 7B5358BC1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F5DF1A11BDCA10200C3A531 /* BeLessThanOrEqualToTest.swift in Sources */, + 1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */, + 1F5DF1AB1BDCA10200C3A531 /* ThrowErrorTest.swift in Sources */, + A8A3B6FB2073644500E25A08 /* ObjcStringersTest.m in Sources */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 7B13BA0F1DD361DF00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + CD79C9B31D2CC848004B6F9A /* ObjCMatchTest.m in Sources */, + 1F5DF19E1BDCA10200C3A531 /* BeGreaterThanTest.swift in Sources */, + 1F5DF1A21BDCA10200C3A531 /* BeLessThanTest.swift in Sources */, + CD79C9AB1D2CC848004B6F9A /* ObjCBeLessThanTest.m in Sources */, + CD79C9A81D2CC848004B6F9A /* ObjCBeIdenticalToTest.m in Sources */, + CD79C9AE1D2CC848004B6F9A /* ObjCBeTruthyTest.m in Sources */, + 1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */, + 1F5DF1A91BDCA10200C3A531 /* MatchTest.swift in Sources */, + A8A3B708207368F100E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F5DF1A81BDCA10200C3A531 /* HaveCountTest.swift in Sources */, + 1F5DF1971BDCA10200C3A531 /* AllPassTest.swift in Sources */, + CD79C9A61D2CC848004B6F9A /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */, + 1FCF91511C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */, + 1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */, + 1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */, + 1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */, + 1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */, + CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */, + 1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */, + CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */, + 1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */, + CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */, + 1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */, + A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */, + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.swift in Sources */, + 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 */, + 1F5DF19F1BDCA10200C3A531 /* BeIdenticalToObjectTest.swift in Sources */, + CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */, + 1F91DD2F1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 6CAEDD0C1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4BB8B81DACAACF0048464B /* ThrowAssertionTest.swift in Sources */, + CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F5DF1991BDCA10200C3A531 /* BeAnInstanceOfTest.swift in Sources */, + CD79C9B11D2CC848004B6F9A /* ObjCEqualTest.m in Sources */, + CD79C9A21D2CC83E004B6F9A /* ObjCBeEmptyTest.m in Sources */, + CD79C9AC1D2CC848004B6F9A /* ObjCBeNilTest.m in Sources */, + CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */, + CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EA8195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */, + 1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */, + 1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */, + 1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */, + 1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */, + AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */, + 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, + 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */, + 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, + DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */, + DDB1BC7A1A92235600F743C3 /* AllPass.swift in Sources */, + 1FD8CD3F1968AB07008ED995 /* BeAKindOf.swift in Sources */, + 1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */, + 7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */, + 1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */, + 1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */, + DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */, + 29EA59671B551EE6002D767E /* ThrowError.swift in Sources */, + 1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */, + 1FD8CD4D1968AB07008ED995 /* BeLessThan.swift in Sources */, + 1FD8CD471968AB07008ED995 /* BeGreaterThan.swift in Sources */, + F8A1BE301CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, + 1F1871DA1CA89EF100A34BF2 /* NMBObjCMatcher.swift in Sources */, + 1FD8CD311968AB07008ED995 /* AdapterProtocols.swift in Sources */, + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */, + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */, + CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 7A0A26231E7F52360092A34E /* ToSucceed.swift in Sources */, + CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */, + CDFB6A3B1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */, + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */, + 1FD8CD451968AB07008ED995 /* BeginWith.swift in Sources */, + 1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD4B1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1FD8CD431968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */, + A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */, + CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + CDFB6A391F7E082500AD8CC7 /* CwlBadInstructionException.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + CDFB6A251F7E07C700AD8CC7 /* CwlCatchException.m in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, + CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */, + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, + 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */, + 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EB3195C0D6300ED456B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4A569B1A3B3539009E1637 /* ObjCEqualTest.m in Sources */, + 1F925EED195C12C800ED456B /* RaisesExceptionTest.swift in Sources */, + 1F925F00195C187600ED456B /* EndWithTest.swift in Sources */, + 1F1B5AD51963E13900CA8BF9 /* BeAKindOfTest.swift in Sources */, + 1F925F0F195C18F500ED456B /* BeLessThanOrEqualToTest.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 */, + 7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */, + 1F925F03195C189500ED456B /* ContainTest.swift in Sources */, + A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */, + 1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */, + 1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */, + 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */, + 1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */, + 1F4A56A11A3B359E009E1637 /* ObjCRaiseExceptionTest.m in Sources */, + A8A3B6FA2073643100E25A08 /* ObjCSatisfyAnyOfTest.m in Sources */, + 1F925F0C195C18E100ED456B /* BeLessThanTest.swift in Sources */, + 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */, + 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */, + 1F91DD2E1C74BF36002C309F /* BeVoidTest.swift in Sources */, + 1F4A56771A3B3253009E1637 /* ObjCBeGreaterThanTest.m in Sources */, + 1F925EFA195C175000ED456B /* BeNilTest.swift in Sources */, + 7A6AB2C21E7F547E00A2F694 /* ToSucceedTest.swift in Sources */, + A8A3B706207368EF00E25A08 /* ObjCSatisfyAllOfTest.m in Sources */, + 1F4A56711A3B319F009E1637 /* ObjCBeCloseToTest.m in Sources */, + 1F4A56981A3B34AA009E1637 /* ObjCEndWithTest.m in Sources */, + 1F4A567D1A3B3311009E1637 /* ObjCBeIdenticalToTest.m in Sources */, + 965B0D0D1B62C06D0005AE66 /* UserDescriptionTest.swift in Sources */, + 1FCF91501C61C85A00B15DCB /* PostNotificationTest.swift in Sources */, + 965B0D0A1B62B8ED0005AE66 /* ObjCUserDescriptionTest.m in Sources */, + 1F4A56921A3B344A009E1637 /* ObjCBeNilTest.m in Sources */, + 1F8A37B11B7C5042001C8357 /* ObjCSyncTest.m in Sources */, + 1F4A56951A3B346F009E1637 /* ObjCContainTest.m in Sources */, + 1F299EAC19627B2D002641AF /* BeEmptyTest.swift in Sources */, + 7B13BA101DD361EA00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m in Sources */, + A8A3B6F5207329DC00E25A08 /* SatisfyAllOfTest.swift in Sources */, + AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */, + 1F4A568C1A3B3407009E1637 /* ObjCBeTrueTest.m in Sources */, + DDEFAEB51A93CBE6005CA37A /* ObjCAllPassTest.m in Sources */, + 1F4A56801A3B333F009E1637 /* ObjCBeLessThanTest.m in Sources */, + 1F925EE7195C121200ED456B /* AsynchronousTest.swift in Sources */, + 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */, + 1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */, + DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */, + 1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */, + 1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */, + 347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */, + 4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */, + 1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */, + 7B5358BB1C3846C900A23FAA /* SatisfyAnyOfTest.swift in Sources */, + 1F925F06195C18B700ED456B /* EqualTest.swift in Sources */, + 1F4A566E1A3B3159009E1637 /* ObjCBeKindOfTest.m in Sources */, + DD72EC651A93874A002F7651 /* AllPassTest.swift in Sources */, + 1F4A569E1A3B3565009E1637 /* ObjCMatchTest.m in Sources */, + 1F925EEA195C124400ED456B /* BeAnInstanceOfTest.swift in Sources */, + 29EA59641B551ED2002D767E /* ThrowErrorTest.swift in Sources */, + 6CAEDD0B1CAEA86F003F1584 /* LinuxSupport.swift in Sources */, + 1F4A566B1A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m in Sources */, + 472FD13A1B9E0A9F00C7B8DA /* HaveCountTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1F1A74371940169200FFFC47 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F1A74361940169200FFFC47 /* PBXContainerItemProxy */; + }; + 1F5DF1611BDCA0CE00C3A531 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F5DF1541BDCA0CE00C3A531 /* Nimble-tvOS */; + targetProxy = 1F5DF1601BDCA0CE00C3A531 /* PBXContainerItemProxy */; + }; + 1F6BB82B1968BFF9009F1DBB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F6BB82A1968BFF9009F1DBB /* PBXContainerItemProxy */; + }; + 1F925EA5195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA4195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EA7195C0C8500ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F1A74281940169200FFFC47 /* Nimble-iOS */; + targetProxy = 1F925EA6195C0C8500ED456B /* PBXContainerItemProxy */; + }; + 1F925EBA195C0D6300ED456B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F925EB9195C0D6300ED456B /* PBXContainerItemProxy */; + }; + 1F9B7BFE1968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFD1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C001968AD760094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7BFF1968AD760094EB8F /* PBXContainerItemProxy */; + }; + 1F9B7C021968AD820094EB8F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F925EAC195C0D6300ED456B /* Nimble-macOS */; + targetProxy = 1F9B7C011968AD820094EB8F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F1A743D1940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1F1A743E1940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_MODULES_AUTOLINK = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 1F1A74401940169200FFFC47 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + "$(inherited)", + ); + 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; + 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; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74411940169200FFFC47 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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)", + ); + 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"; + 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; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 1F1A74431940169200FFFC47 /* Debug */ = { + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + OTHER_CODE_SIGN_FLAGS = "--verbose"; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F1A74441940169200FFFC47 /* Release */ = { + 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"; + 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"; + }; + name = Release; + }; + 1F5DF1661BDCA0CE00C3A531 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/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; + PRODUCT_NAME = Nimble; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 1F5DF1671BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + 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 = ( + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Nimble/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F5DF1681BDCA0CE00C3A531 /* Debug */ = { + 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"; + 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; + }; + name = Debug; + }; + 1F5DF1691BDCA0CE00C3A531 /* Release */ = { + isa = XCBuildConfiguration; + 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"; + 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"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 1F925EC1195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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", + "PRODUCT_NAME=$(PRODUCT_NAME)/$(PRODUCT_NAME)", + "$(inherited)", + ); + 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"; + 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 = { + 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)", + "$(inherited)", + ); + 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"; + 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; + }; + name = Release; + }; + 1F925EC4195C0D6300ED456B /* Debug */ = { + isa = XCBuildConfiguration; + 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"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1F925EC5195C0D6300ED456B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + 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"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = NimbleTests; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + A8F2B2551E79A4AB005BDD17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Debug; + }; + A8F2B2561E79A4AB005BDD17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F1A74231940169200FFFC47 /* Build configuration list for PBXProject "Nimble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A743D1940169200FFFC47 /* Debug */, + 1F1A743E1940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74401940169200FFFC47 /* Debug */, + 1F1A74411940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F1A74421940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F1A74431940169200FFFC47 /* Debug */, + 1F1A74441940169200FFFC47 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1661BDCA0CE00C3A531 /* Debug */, + 1F5DF1671BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F5DF16B1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F5DF1681BDCA0CE00C3A531 /* Debug */, + 1F5DF1691BDCA0CE00C3A531 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC1195C0D6300ED456B /* Debug */, + 1F925EC2195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F925EC3195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F925EC4195C0D6300ED456B /* Debug */, + 1F925EC5195C0D6300ED456B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8F2B2571E79A4AC005BDD17 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8F2B2551E79A4AB005BDD17 /* Debug */, + A8F2B2561E79A4AB005BDD17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F1A74201940169200FFFC47 /* Project object */; +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..80405c9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..d640838 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..c45d780 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift new file mode 100644 index 0000000..8d0b745 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:3.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift new file mode 100644 index 0000000..740b842 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Package@swift-4.swift @@ -0,0 +1,22 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + products: [ + .library(name: "Nimble", targets: ["Nimble"]), + ], + targets: [ + .target( + name: "Nimble", + dependencies: [] + ), + .testTarget( + name: "NimbleTests", + dependencies: ["Nimble"], + exclude: ["objc"] + ), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/README.md b/Carthage/Checkouts/Quick/Externals/Nimble/README.md new file mode 100644 index 0000000..19c562f --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/README.md @@ -0,0 +1,1764 @@ +# Nimble + +[![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) +[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble) + +Use Nimble to express the expected outcomes of Swift +or Objective-C expressions. Inspired by +[Cedar](https://github.com/pivotal/cedar). + +```swift +// Swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + +# How to Use Nimble + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest) +- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto) + - [Custom Failure Messages](#custom-failure-messages) + - [Type Safety](#type-safety) + - [Operator Overloads](#operator-overloads) + - [Lazily Computed Values](#lazily-computed-values) + - [C Primitives](#c-primitives) + - [Asynchronous Expectations](#asynchronous-expectations) + - [Objective-C Support](#objective-c-support) + - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand) +- [Built-in Matcher Functions](#built-in-matcher-functions) + - [Type Checking](#type-checking) + - [Equivalence](#equivalence) + - [Identity](#identity) + - [Comparisons](#comparisons) + - [Types/Classes](#typesclasses) + - [Truthiness](#truthiness) + - [Swift Assertions](#swift-assertions) + - [Swift Error Handling](#swift-error-handling) + - [Exceptions](#exceptions) + - [Collection Membership](#collection-membership) + - [Strings](#strings) + - [Collection Elements](#collection-elements) + - [Collection Count](#collection-count) + - [Notifications](#notifications) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) + - [Custom Validation](#custom-validation) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [PredicateResult](#predicateresult) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Basic Customization](#basic-customization) + - [Full Customization](#full-customization) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) + - [Migrating from the Old Matcher API](#migrating-from-the-old-matcher-api) + - [Minimal Step - Use `.predicate`](#minimal-step---use-predicate) + - [Convert to use `Predicate` Type with Old Matcher Constructor](#convert-to-use-predicate-type-with-old-matcher-constructor) + - [Convert to `Predicate` Type with Preferred Constructor](#convert-to-predicate-type-with-preferred-constructor) + - [Deprecation Roadmap](#deprecation-roadmap) +- [Installing Nimble](#installing-nimble) + - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule) + - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods) + - [Using Nimble without XCTest](#using-nimble-without-xctest) + + + +# Some Background: Expressing Outcomes Using Assertions in XCTest + +Apple's Xcode includes the XCTest framework, which provides +assertion macros to test whether code behaves properly. +For example, to assert that `1 + 1 = 2`, XCTest has you write: + +```swift +// Swift + +XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two") +``` + +Or, in Objective-C: + +```objc +// Objective-C + +XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two"); +``` + +XCTest assertions have a couple of drawbacks: + +1. **Not enough macros.** There's no easy way to assert that a string + contains a particular substring, or that a number is less than or + equal to another. +2. **It's hard to write asynchronous tests.** XCTest forces you to write + a lot of boilerplate code. + +Nimble addresses these concerns. + +# Nimble: Expectations Using `expect(...).to` + +Nimble allows you to express expectations using a natural, +easily understood language: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).to(equal("Squee!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).to(equal(@"Squee!")); +``` + +> The `expect` function autocompletes to include `file:` and `line:`, + but these parameters are optional. Use the default values to have + Xcode highlight the correct line when an expectation is not met. + +To perform the opposite expectation--to assert something is *not* +equal--use `toNot` or `notTo`: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).toNot(equal("Oh, hello there!")) +expect(seagull.squawk).notTo(equal("Oh, hello there!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).toNot(equal(@"Oh, hello there!")); +expect(seagull.squawk).notTo(equal(@"Oh, hello there!")); +``` + +## Custom Failure Messages + +Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text: + +```swift +// Swift + +expect(1 + 1).to(equal(3)) +// failed - expected to equal <3>, got <2> + +expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded") +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3>, got <2> +``` + +Or the *WithDescription version in Objective-C: + +```objc +// Objective-C + +@import Nimble; + +expect(@(1+1)).to(equal(@3)); +// failed - expected to equal <3.0000>, got <2.0000> + +expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded"); +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3.0000>, got <2.0000> +``` + +## Type Safety + +Nimble makes sure you don't compare two types that don't match: + +```swift +// Swift + +// Does not compile: +expect(1 + 1).to(equal("Squee!")) +``` + +> Nimble uses generics--only available in Swift--to ensure + type correctness. That means type checking is + not available when using Nimble in Objective-C. :sob: + +## Operator Overloads + +Tired of so much typing? With Nimble, you can use overloaded operators +like `==` for equivalence, or `>` for comparisons: + +```swift +// Swift + +// Passes if squawk does not equal "Hi!": +expect(seagull.squawk) != "Hi!" + +// Passes if 10 is greater than 2: +expect(10) > 2 +``` + +> Operator overloads are only available in Swift, so you won't be able + to use this syntax in Objective-C. :broken_heart: + +## Lazily Computed Values + +The `expect` function doesn't evaluate the value it's given until it's +time to match. So Nimble can test whether an expression raises an +exception once evaluated: + +```swift +// Swift + +// Note: Swift currently doesn't have exceptions. +// Only Objective-C code can raise exceptions +// that Nimble will catch. +// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064) +let exception = NSException( + name: NSInternalInconsistencyException, + reason: "Not enough fish in the sea.", + userInfo: ["something": "is fishy"]) +expect { exception.raise() }.to(raiseException()) + +// Also, you can customize raiseException to be more specific +expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException)) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea")) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea", + userInfo: ["something": "is fishy"])) +``` + +Objective-C works the same way, but you must use the `expectAction` +macro when making an expectation on an expression that has no return +value: + +```objc +// Objective-C + +NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Not enough fish in the sea." + userInfo:nil]; +expectAction(^{ [exception raise]; }).to(raiseException()); + +// Use the property-block syntax to be more specific. +expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException)); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea")); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea"). + userInfo(@{@"something": @"is fishy"})); + +// You can also pass a block for custom matching of the raised exception +expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(NSInternalInconsistencyException)); +})); +``` + +## C Primitives + +Some testing frameworks make it hard to test primitive C values. +In Nimble, it just works: + +```swift +// Swift + +let actual: CInt = 1 +let expectedValue: CInt = 1 +expect(actual).to(equal(expectedValue)) +``` + +In fact, Nimble uses type inference, so you can write the above +without explicitly specifying both types: + +```swift +// Swift + +expect(1 as CInt).to(equal(1)) +``` + +> In Objective-C, Nimble only supports Objective-C objects. To + make expectations on primitive C values, wrap then in an object + literal: + +```objc +expect(@(1 + 1)).to(equal(@2)); +``` + +## Asynchronous Expectations + +In Nimble, it's easy to make expectations on values that are updated +asynchronously. Just use `toEventually` or `toEventuallyNot`: + +```swift +// Swift 3.0 and later + +DispatchQueue.main.async { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```swift +// Swift 2.3 and earlier + +dispatch_async(dispatch_get_main_queue()) { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```objc +// Objective-C + +dispatch_async(dispatch_get_main_queue(), ^{ + [ocean add:@"dolphins"]; + [ocean add:@"whales"]; +}); +expect(ocean).toEventually(contain(@"dolphins", @"whales")); +``` + +Note: toEventually triggers its polls on the main thread. Blocking the main +thread will cause Nimble to stop the run loop. This can cause test pollution +for whatever incomplete code that was running on the main thread. Blocking the +main thread can be caused by blocking IO, calls to sleep(), deadlocks, and +synchronous IPC. + +In the above example, `ocean` is constantly re-evaluated. If it ever +contains dolphins and whales, the expectation passes. If `ocean` still +doesn't contain them, even after being continuously re-evaluated for one +whole second, the expectation fails. + +Sometimes it takes more than a second for a value to update. In those +cases, use the `timeout` parameter: + +```swift +// Swift + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).toEventually(contain("starfish"), timeout: 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) +``` + +```objc +// Objective-C + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).withTimeout(3).toEventually(contain(@"starfish")); +``` + +You can also provide a callback by using the `waitUntil` function: + +```swift +// Swift + +waitUntil { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + ocean.goFish { success in + expect(success).to(beTrue()) + done() + } +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + [ocean goFishWithHandler:^(BOOL success){ + expect(success).to(beTrue()); + done(); + }]; +}); +``` + +Note: `waitUntil` triggers its timeout code on the main thread. Blocking the main +thread will cause Nimble to stop the run loop to continue. This can cause test +pollution for whatever incomplete code that was running on the main thread. +Blocking the main thread can be caused by blocking IO, calls to sleep(), +deadlocks, and synchronous IPC. + +In some cases (e.g. when running on slower machines) it can be useful to modify +the default timeout and poll interval values. This can be done as follows: + +```swift +// Swift + +// Increase the global timeout to 5 seconds: +Nimble.AsyncDefaults.Timeout = 5 + +// Slow the polling interval to 0.1 seconds: +Nimble.AsyncDefaults.PollInterval = 0.1 +``` + +## Objective-C Support + +Nimble has full support for Objective-C. However, there are two things +to keep in mind when using Nimble in Objective-C: + +1. All parameters passed to the `expect` function, as well as matcher + functions like `equal`, must be Objective-C objects or can be converted into + an `NSObject` equivalent: + + ```objc + // Objective-C + + @import Nimble; + + expect(@(1 + 1)).to(equal(@2)); + expect(@"Hello world").to(contain(@"world")); + + // Boxed as NSNumber * + expect(2).to(equal(2)); + expect(1.2).to(beLessThan(2.0)); + expect(true).to(beTruthy()); + + // Boxed as NSString * + expect("Hello world").to(equal("Hello world")); + + // Boxed as NSRange + expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10))); + ``` + +2. To make an expectation on an expression that does not return a value, + such as `-[NSException raise]`, use `expectAction` instead of + `expect`: + + ```objc + // Objective-C + + expectAction(^{ [exception raise]; }).to(raiseException()); + ``` + +The following types are currently converted to an `NSObject` type: + + - **C Numeric types** are converted to `NSNumber *` + - `NSRange` is converted to `NSValue *` + - `char *` is converted to `NSString *` + +For the following matchers: + +- `equal` +- `beGreaterThan` +- `beGreaterThanOrEqual` +- `beLessThan` +- `beLessThanOrEqual` +- `beCloseTo` +- `beTrue` +- `beFalse` +- `beTruthy` +- `beFalsy` +- `haveCount` + +If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues). + +## Disabling Objective-C Shorthand + +Nimble provides a shorthand for expressing expectations using the +`expect` function. To disable this shorthand in Objective-C, define the +`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before +importing Nimble: + +```objc +#define NIMBLE_DISABLE_SHORT_SYNTAX 1 + +@import Nimble; + +NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!")); +``` + +> Disabling the shorthand is useful if you're testing functions with + names that conflict with Nimble functions, such as `expect` or + `equal`. If that's not the case, there's no point in disabling the + shorthand. + +# Built-in Matcher Functions + +Nimble includes a wide variety of matcher functions. + +## Type Checking + +Nimble supports checking the type membership of any kind of object, whether +Objective-C conformant or not: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// The following tests pass +expect(1).to(beAKindOf(Int.self)) +expect("turtle").to(beAKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beAKindOf(SomeProtocol.self)) +expect(classObject).to(beAKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beAKindOf(SomeProtocol.self)) +expect(structObject).to(beAKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAKindOf(SomeClassConformingToProtocol.self)) +``` + +```objc +// Objective-C + +// The following tests pass +NSMutableArray *array = [NSMutableArray array]; +expect(array).to(beAKindOf([NSArray class])); +expect(@1).toNot(beAKindOf([NSNull class])); +``` + +Objects can be tested for their exact types using the `beAnInstanceOf` matcher: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only +// passes if the object is the EXACT type requested. The following +// tests pass -- note its behavior when working in an inheritance hierarchy. +expect(1).to(beAnInstanceOf(Int.self)) +expect("turtle").to(beAnInstanceOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self)) +``` + +## Equivalence + +```swift +// Swift + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) +expect(actual) == expected + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +expect(actual) != expected +``` + +```objc +// Objective-C + +// Passes if 'actual' is equivalent to 'expected': +expect(actual).to(equal(expected)) + +// Passes if 'actual' is not equivalent to 'expected': +expect(actual).toNot(equal(expected)) +``` + +Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`. +`equal` will always fail when used to compare one or more `nil` values. + +## Identity + +```swift +// Swift + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)) +expect(actual) === expected + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)) +expect(actual) !== expected +``` + +It is important to remember that `beIdenticalTo` only makes sense when comparing +types with reference semantics, which have a notion of identity. In Swift, +that means types that are defined as a `class`. + +This matcher will not work when comparing types with value semantics such as +those defined as a `struct` or `enum`. If you need to compare two value types, +consider what it means for instances of your type to be identical. This may mean +comparing individual properties or, if it makes sense to do so, conforming your type +to `Equatable` and using Nimble's equivalence matchers instead. + + +```objc +// Objective-C + +// Passes if 'actual' has the same pointer address as 'expected': +expect(actual).to(beIdenticalTo(expected)); + +// Passes if 'actual' does not have the same pointer address as 'expected': +expect(actual).toNot(beIdenticalTo(expected)); +``` + +## Comparisons + +```swift +// Swift + +expect(actual).to(beLessThan(expected)) +expect(actual) < expected + +expect(actual).to(beLessThanOrEqualTo(expected)) +expect(actual) <= expected + +expect(actual).to(beGreaterThan(expected)) +expect(actual) > expected + +expect(actual).to(beGreaterThanOrEqualTo(expected)) +expect(actual) >= expected +``` + +```objc +// Objective-C + +expect(actual).to(beLessThan(expected)); +expect(actual).to(beLessThanOrEqualTo(expected)); +expect(actual).to(beGreaterThan(expected)); +expect(actual).to(beGreaterThanOrEqualTo(expected)); +``` + +> Values given to the comparison matchers above must implement + `Comparable`. + +Because of how computers represent floating point numbers, assertions +that two floating point numbers be equal will sometimes fail. To express +that two numbers should be close to one another within a certain margin +of error, use `beCloseTo`: + +```swift +// Swift + +expect(actual).to(beCloseTo(expected, within: delta)) +``` + +```objc +// Objective-C + +expect(actual).to(beCloseTo(expected).within(delta)); +``` + +For example, to assert that `10.01` is close to `10`, you can write: + +```swift +// Swift + +expect(10.01).to(beCloseTo(10, within: 0.1)) +``` + +```objc +// Objective-C + +expect(@(10.01)).to(beCloseTo(@10).within(0.1)); +``` + +There is also an operator shortcut available in Swift: + +```swift +// Swift + +expect(actual) ≈ expected +expect(actual) ≈ (expected, delta) + +``` +(Type option+x to get `≈` on a U.S. keyboard) + +The former version uses the default delta of 0.0001. Here is yet another way to do this: + +```swift +// Swift + +expect(actual) ≈ expected ± delta +expect(actual) == expected ± delta + +``` +(Type option+shift+= to get `±` on a U.S. keyboard) + +If you are comparing arrays of floating point numbers, you'll find the following useful: + +```swift +// Swift + +expect([0.0, 2.0]) ≈ [0.0001, 2.0001] +expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1)) + +``` + +> Values given to the `beCloseTo` matcher must be coercable into a + `Double`. + +## Types/Classes + +```swift +// Swift + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)) + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)) +``` + +```objc +// Objective-C + +// Passes if 'instance' is an instance of 'aClass': +expect(instance).to(beAnInstanceOf(aClass)); + +// Passes if 'instance' is an instance of 'aClass' or any of its subclasses: +expect(instance).to(beAKindOf(aClass)); +``` + +> Instances must be Objective-C objects: subclasses of `NSObject`, + or Swift objects bridged to Objective-C with the `@objc` prefix. + +For example, to assert that `dolphin` is a kind of `Mammal`: + +```swift +// Swift + +expect(dolphin).to(beAKindOf(Mammal)) +``` + +```objc +// Objective-C + +expect(dolphin).to(beAKindOf([Mammal class])); +``` + +> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to + test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`. + +## Truthiness + +```swift +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()) + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()) + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()) + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()) + +// Passes if 'actual' is nil: +expect(actual).to(beNil()) +``` + +```objc +// Objective-C + +// Passes if 'actual' is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()); + +// Passes if 'actual' is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()); + +// Passes if 'actual' is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()); + +// Passes if 'actual' is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()); + +// Passes if 'actual' is nil: +expect(actual).to(beNil()); +``` + +## Swift Assertions + +If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an assertion, +// such as by calling 'fatalError()' or if a precondition fails: +expect { try somethingThatThrows() }.to(throwAssertion()) +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing an NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the code after the precondition check is not run: +var reachedPoint1 = false +var reachedPoint2 = false +expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true +}.to(throwAssertion()) + +expect(reachedPoint1) == true +expect(reachedPoint2) == false +``` + +Notes: + +* This feature is only available in Swift. +* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_. +* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration. + +## Swift Error Handling + +If you're using Swift 2.0 or newer, you can use the `throwError` matcher to check if an error is thrown. + +Note: +The following code sample references the `Swift.Error` protocol. +This is `Swift.ErrorProtocol` in versions of Swift prior to version 3.0. + +```swift +// Swift + +// Passes if 'somethingThatThrows()' throws an 'Error': +expect { try somethingThatThrows() }.to(throwError()) + +// Passes if 'somethingThatThrows()' throws an error within a particular domain: +expect { try somethingThatThrows() }.to(throwError { (error: Error) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if 'somethingThatThrows()' throws a particular error enum case: +expect { try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if 'somethingThatThrows()' throws an error of a particular type: +expect { try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +When working directly with `Error` values, using the `matchError` matcher +allows you to perform certain checks on the error itself without having to +explicitly cast the error. + +The `matchError` matcher allows you to check whether or not the error: + +- is the same _type_ of error you are expecting. +- represents a particular error value that you are expecting. + +This can be useful when using `Result` or `Promise` types, for example. + +```swift +// Swift + +let actual: Error = ... + +// Passes if 'actual' represents any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.self)) + +// Passes if 'actual' represents the case 'timeout' from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.timeout)) + +// Passes if 'actual' contains an NSError equal to the one provided: +expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil))) +``` + +Note: This feature is only available in Swift. + +## Exceptions + +```swift +// Swift + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name: +expect(actual).to(raiseException(named: name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException(named: name, reason: reason)) + +// Passes if 'actual' raises an exception which passes expectations defined in the given closure: +// (in this case, if the exception's name begins with "a r") +expect { exception.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(beginWith("a r")) +}) +``` + +```objc +// Objective-C + +// Passes if 'actual', when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if 'actual' raises an exception with the given name +expect(actual).to(raiseException().named(name)) + +// Passes if 'actual' raises an exception with the given name and reason: +expect(actual).to(raiseException().named(name).reason(reason)) + +// Passes if 'actual' raises an exception and it passes expectations defined in the given block: +// (in this case, if name begins with "a r") +expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(@"a r")); +})); +``` + +Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)). +Only Objective-C code can raise exceptions that Nimble will catch. + +## Collection Membership + +```swift +// Swift + +// Passes if all of the expected values are members of 'actual': +expect(actual).to(contain(expected...)) + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()) +``` + +```objc +// Objective-C + +// Passes if expected is a member of 'actual': +expect(actual).to(contain(expected)); + +// Passes if 'actual' is empty (i.e. it contains no elements): +expect(actual).to(beEmpty()); +``` + +> In Swift `contain` takes any number of arguments. The expectation + passes if all of them are members of the collection. In Objective-C, + `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27). + +For example, to assert that a list of sea creature names contains +"dolphin" and "starfish": + +```swift +// Swift + +expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish")) +``` + +```objc +// Objective-C + +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin")); +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish")); +``` + +> `contain` and `beEmpty` expect collections to be instances of + `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements. + +To test whether a set of elements is present at the beginning or end of +an ordered collection, use `beginWith` and `endWith`: + +```swift +// Swift + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected...)) + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected...)) +``` + +```objc +// Objective-C + +// Passes if the elements in expected appear at the beginning of 'actual': +expect(actual).to(beginWith(expected)); + +// Passes if the the elements in expected come at the end of 'actual': +expect(actual).to(endWith(expected)); +``` + +> `beginWith` and `endWith` expect collections to be instances of + `NSArray`, or ordered Swift collections composed of `Equatable` + elements. + + Like `contain`, in Objective-C `beginWith` and `endWith` only support + a single argument [for now](https://github.com/Quick/Nimble/issues/27). + +For code that returns collections of complex objects without a strict +ordering, there is the `containElementSatisfying` matcher: + +```swift +// Swift + +struct Turtle { + let color: String +} + +let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "green" +})) +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "blue" +}, "that is a turtle with color 'blue'")) + +// The second matcher will incorporate the provided string in the error message +// should it fail +``` + +```objc +// Objective-C + +@interface Turtle : NSObject +@property (nonatomic, readonly, nonnull) NSString *color; +@end + +@implementation Turtle +@end + +NSArray * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes regardless of whether the array is +// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]: + +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) { + return [[turtle color] isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(substring)) + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)) + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)) + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()) + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains 'substring': +expect(actual).to(contain(expected)); + +// Passes if 'actual' begins with 'prefix': +expect(actual).to(beginWith(prefix)); + +// Passes if 'actual' ends with 'suffix': +expect(actual).to(endWith(suffix)); + +// Passes if 'actual' represents the empty string, "": +expect(actual).to(beEmpty()); + +// Passes if 'actual' matches the regular expression defined in 'expected': +expect(actual).to(match(expected)) +``` + +## Collection Elements + +Nimble provides a means to check that all elements of a collection pass a given expectation. + +### Swift + +In Swift, the collection must be an instance of a type conforming to +`Sequence`. + +```swift +// Swift + +// Providing a custom function: +expect([1, 2, 3, 4]).to(allPass { $0! < 5 }) + +// Composing the expectation with another matcher: +expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) +``` + +### Objective-C + +In Objective-C, the collection must be an instance of a type which implements +the `NSFastEnumeration` protocol, and whose elements are instances of a type +which subclasses `NSObject`. + +Additionally, unlike in Swift, there is no override to specify a custom +matcher function. + +```objc +// Objective-C + +expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@5))); +``` + +## Collection Count + +```swift +// Swift + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// Passes if 'actual' contains the 'expected' number of elements: +expect(actual).to(haveCount(expected)) + +// Passes if 'actual' does _not_ contain the 'expected' number of elements: +expect(actual).notTo(haveCount(expected)) +``` + +For Swift, the actual value must be an instance of a type conforming to `Collection`. +For example, instances of `Array`, `Dictionary`, or `Set`. + +For Objective-C, the actual value must be one of the following classes, or their subclasses: + + - `NSArray`, + - `NSDictionary`, + - `NSSet`, or + - `NSHashTable`. + +## Notifications + +```swift +// Swift +let testNotification = Notification(name: "Foo", object: nil) + +// passes if the closure in expect { ... } posts a notification to the default +// notification center. +expect { + NotificationCenter.default.postNotification(testNotification) +}.to(postNotifications(equal([testNotification])) + +// 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)) +``` + +> This matcher is only available in Swift. + +## Matching a value to any of a group of matchers + +```swift +// Swift + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7))) + +// in Swift you also have the option to use the || operator to achieve a similar function +expect(82).to(beLessThan(50) || beGreaterThan(80)) +``` + +```objc +// Objective-C + +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7))) +``` + +Note: This matcher allows you to chain any number of matchers together. This provides flexibility, + but if you find yourself chaining many matchers together in one test, consider whether you + could instead refactor that single test into multiple, more precisely focused tests for + better coverage. + +## Custom Validation + +```swift +// Swift + +// passes if .succeeded is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).to(succeed()) + +// passes if .failed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed(reason: "wrong enum case") + } + + return .succeeded +}).notTo(succeed()) +``` + +The `String` provided with `.failed()` is shown when the test fails. + +When using `toEventually()` be careful not to make state changes or run process intensive code since this closure will be ran many times. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `Predicate` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> Predicate { + // Can be shortened to: + // Predicate { actual in ... } + // + // But shown with types here for clarity. + return Predicate { (actual: Expression) throws -> PredicateResult in + let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>") + if let actualValue = try actualExpression.evaluate() { + return PredicateResult( + bool: actualValue == expectedValue!, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} +``` + +The return value of a `Predicate` closure is a `PredicateResult` that indicates +whether the actual value matches the expectation and what error message to +display on failure. + +> The actual `equal` matcher function does not match when + `expected` are nil; the example above has been edited for brevity. + +Since matchers are just Swift functions, you can define them anywhere: +at the top of your test file, in a file shared by all of your tests, or +in an Xcode project you distribute to others. + +> If you write a matcher you think everyone can use, consider adding it + to Nimble's built-in set of matchers by sending a pull request! Or + distribute it yourself via GitHub. + +For examples of how to write your own matchers, just check out the +[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers) +to see how Nimble's built-in set of matchers are implemented. You can +also check out the tips below. + +## PredicateResult + +`PredicateResult` is the return struct that `Predicate` return to indicate +success and failure. A `PredicateResult` is made up of two values: +`PredicateStatus` and `ExpectationMessage`. + +Instead of a boolean, `PredicateStatus` captures a trinary set of values: + +```swift +// Swift + +public enum PredicateStatus { +// The predicate "passes" with the given expression +// eg - expect(1).to(equal(1)) +case matches + +// The predicate "fails" with the given expression +// eg - expect(1).toNot(equal(1)) +case doesNotMatch + +// The predicate never "passes" with the given expression, even if negated +// eg - expect(nil as Int?).toNot(equal(1)) +case fail + +// ... +} +``` + +Meanwhile, `ExpectationMessage` provides messaging semantics for error reporting. + +```swift +// Swift + +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// ... +} +``` + +Predicates should usually depend on either `.expectedActualValueTo(..)` or +`.fail(..)` when reporting errors. Special cases can be used for the other enum +cases. + +Finally, if your Predicate utilizes other Predicates, you can utilize +`.appended(details:)` and `.appended(message:)` methods to annotate an existing +error with more details. + +A common message to append is failing on nils. For that, `.appendedBeNilHint()` +can be used. + +## Lazy Evaluation + +`actualExpression` is a lazy, memoized closure around the value provided to the +`expect` function. The expression can either be a closure or a value directly +passed to `expect(...)`. In order to determine whether that value matches, +custom matchers should call `actualExpression.evaluate()`: + +```swift +// Swift + +public func beNil() -> Predicate { + // Predicate.simpleNilable(..) automatically generates ExpectationMessage for + // us based on the string we provide to it. Also, the 'Nilable' postfix indicates + // that this Predicate supports matching against nil actualExpressions, instead of + // always resulting in a PredicateStatus.fail result -- which is true for + // Predicate.simple(..) + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} +``` + +In the above example, `actualExpression` is not `nil` -- it is a closure +that returns a value. The value it returns, which is accessed via the +`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil` +matcher function returns `true`, indicating that the expectation passed. + +## Type Checking via Swift Generics + +Using Swift's generics, matchers can constrain the type of the actual value +passed to the `expect` function by modifying the return type. + +For example, the following matcher, `haveDescription`, only accepts actual +values that implement the `Printable` protocol. It checks their `description` +against the one provided to the matcher function, and passes if they are the same: + +```swift +// Swift + +public func haveDescription(description: String) -> Predicate { + return Predicate.simple("have description") { actual in + return PredicateStatus(bool: actual.evaluate().description == description) + } +} +``` + +## Customizing Failure Messages + +When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble +outputs the following failure message when an expectation fails: + +```swift +// where `message` is the first string argument and +// `actual` is the actual value received in `expect(..)` +"expected to \(message), got <\(actual)>" +``` + +You can customize this message by modifying the way you create a `Predicate`. + +### Basic Customization + +For slightly more complex error messaging, receive the created failure message +with `Predicate.define(..)`: + +```swift +// Swift + +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(bool: matches, message: msg) + } +} +``` + +In the example above, `msg` is defined based on the string given to +`Predicate.define`. The code looks akin to: + +```swift +// Swift + +let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedValue))>") +``` + +### Full Customization + +To fully customize the behavior of the Predicate, use the overload that expects +a `PredicateResult` to be returned. + +Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use: + +```swift +public indirect enum ExpectationMessage { +// Emits standard error message: +// eg - "expected to , got " +case expectedActualValueTo(/* message: */ String) + +// Allows any free-form message +// eg - "" +case fail(/* message: */ String) + +// Emits standard error message with a custom actual value instead of the default. +// eg - "expected to , got " +case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + +// Emits standard error message without mentioning the actual value +// eg - "expected to " +case expectedTo(/* message: */ String) + +// ... +} +``` + +For matchers that compose other matchers, there are a handful of helper +functions to annotate messages. + +`appended(message: String)` is used to append to the original failure message: + +```swift +// produces "expected to be true, got (use beFalse() for inverse)" +// appended message do show up inline in Xcode. +.expectedActualValueTo("be true").appended(message: " (use beFalse() for inverse)") +``` + +For a more comprehensive message that spans multiple lines, use +`appended(details: String)` instead: + +```swift +// produces "expected to be true, got \n\nuse beFalse() for inverse\nor use beNil()" +// details do not show inline in Xcode, but do show up in test logs. +.expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()") +``` + +## 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 +custom matcher. The example below defines the class method +`+[NMBObjCMatcher 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) + } + } +} +``` + +The above allows you to use the matcher from Objective-C: + +```objc +// Objective-C + +expect(actual).to([NMBObjCMatcher beNilMatcher]()); +``` + +To make the syntax easier to use, define a C function that calls the +class method: + +```objc +// Objective-C + +FOUNDATION_EXPORT id beNil() { + return [NMBObjCMatcher beNilMatcher]; +} +``` + +### Properly Handling `nil` in Objective-C Matchers + +When supporting Objective-C, make sure you handle `nil` appropriately. +Like [Cedar](https://github.com/pivotal/cedar/issues/100), +**most matchers do not match with nil**. This is to bring prevent test +writers from being surprised by `nil` values where they did not expect +them. + +Nimble provides the `beNil` matcher function for test writer that want +to make expectations on `nil` objects: + +```objc +// Objective-C + +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. + +```swift + +public func beginWith(startingElement: T) -> NonNilMatcherFunc { + 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 + } +} + +extension NMBObjCMatcher { + public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.evaluate() + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } +} +``` + +## Migrating from the Old Matcher API + +Previously (`<7.0.0`), Nimble supported matchers via the following types: + +- `Matcher` +- `NonNilMatcherFunc` +- `MatcherFunc` + +All of those types have been replaced by `Predicate`. While migrating can be a +lot of work, Nimble currently provides several steps to aid migration of your +custom matchers: + +### Minimal Step - Use `.predicate` + +Nimble provides an extension to the old types that automatically naively +converts those types to the newer `Predicate`. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + 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 + }.predicate +} +``` + +This is the simpliest way to externally support `Predicate` which allows easier +composition than the old Nimble matcher interface, with minimal effort to change. + +### Convert to use `Predicate` Type with Old Matcher Constructor + +The second most convenient step is to utilize special constructors that +`Predicate` supports that closely align to the constructors of the old Nimble +matcher types. + +```swift +// Swift +public func beginWith(startingElement: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} +``` + +This allows you to completely drop the old types from your code, although the +intended behavior may alter slightly to what is desired. + +### Convert to `Predicate` Type with Preferred Constructor + +Finally, you can convert to the native `Predicate` format using one of the +constructors not used to assist in the migration. + +### Deprecation Roadmap + +Nimble 7 introduces `Predicate` but will support the old types with warning +deprecations. A couple major releases of Nimble will remain backwards +compatible with the old matcher api, although new features may not be +backported. + +The deprecating plan is a 3 major versions removal. Which is as follows: + + 1. Introduce new `Predicate` API, deprecation warning for old matcher APIs. + (Nimble `v7.x.x`) + 2. Introduce warnings on migration-path features (`.predicate`, + `Predicate`-constructors with similar arguments to old API). (Nimble + `v8.x.x`) + 3. Remove old API. (Nimble `v9.x.x`) + + +# Installing Nimble + +> Nimble can be used on its own, or in conjunction with its sister + project, [Quick](https://github.com/Quick/Quick). To install both + Quick and Nimble, follow [the installation instructions in the Quick + Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md). + +Nimble can currently be installed in one of two ways: using CocoaPods, or with +git submodules. + +## Installing Nimble as a Submodule + +To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow +these 4 easy steps: + +1. Clone the Nimble repository +2. Add Nimble.xcodeproj to the Xcode workspace for your project +3. Link Nimble.framework to your test target +4. Start writing expectations! + +For more detailed instructions on each of these steps, +read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick). +Ignore the steps involving adding Quick to your project in order to +install just Nimble. + +## Installing Nimble via CocoaPods + +To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add +Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift +support for CocoaPods. + +```ruby +platform :ios, '8.0' + +source 'https://github.com/CocoaPods/Specs.git' + +# Whatever pods you need for your app go here + +target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do + use_frameworks! + pod 'Nimble', '~> 6.0.0' +end +``` + +Finally run `pod install`. + +## Using Nimble without XCTest + +Nimble is integrated with XCTest to allow it work well when used in Xcode test +bundles, however it can also be used in a standalone app. After installing +Nimble using one of the above methods, there are two additional steps required +to make this work. + +1. Create a custom assertion handler and assign an instance of it to the + global `NimbleAssertionHandler` variable. For example: + +```swift +class MyAssertionHandler : AssertionHandler { + func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) { + if (!assertion) { + print("Expectation failed: \(message.stringValue)") + } + } +} +``` +```swift +// Somewhere before you use any assertions +NimbleAssertionHandler = MyAssertionHandler() +``` + +2. Add a post-build action to fix an issue with the Swift XCTest support + library being unnecessarily copied into your app + * Edit your scheme in Xcode, and navigate to Build -> Post-actions + * Click the "+" icon and select "New Run Script Action" + * Open the "Provide build settings from" dropdown and select your target + * Enter the following script contents: +``` +rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib" +``` + +You can now use Nimble assertions in your code and handle failures as you see +fit. diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift @@ -0,0 +1,17 @@ +import Foundation + +/// Protocol for the assertion handler that Nimble uses for all expectations. +public protocol AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) +} + +/// Global backing interface for assertions that Nimble creates. +/// Defaults to a private test handler that passes through to XCTest. +/// +/// If XCTest is not available, you must assign your own assertion handler +/// before using any matchers, otherwise Nimble will abort the program. +/// +/// @see AssertionHandler +public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in + return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() +}() diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift @@ -0,0 +1,19 @@ +/// AssertionDispatcher allows multiple AssertionHandlers to receive +/// assertion messages. +/// +/// @warning Does not fully dispatch if one of the handlers raises an exception. +/// This is possible with XCTest-based assertion handlers. +/// +public class AssertionDispatcher: AssertionHandler { + let handlers: [AssertionHandler] + + public init(handlers: [AssertionHandler]) { + self.handlers = handlers + } + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + for handler in handlers { + handler.assert(assertion, message: message, location: location) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift @@ -0,0 +1,100 @@ +import Foundation + +/// A data structure that stores information about an assertion when +/// AssertionRecorder is set as the Nimble assertion handler. +/// +/// @see AssertionRecorder +/// @see AssertionHandler +public struct AssertionRecord: CustomStringConvertible { + /// Whether the assertion succeeded or failed + public let success: Bool + /// The failure message the assertion would display on failure. + public let message: FailureMessage + /// The source location the expectation occurred on. + public let location: SourceLocation + + public var description: String { + return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" + } +} + +/// An AssertionHandler that silently records assertions that Nimble makes. +/// This is useful for testing failure messages for matchers. +/// +/// @see AssertionHandler +public class AssertionRecorder: AssertionHandler { + /// All the assertions that were captured by this recorder + public var assertions = [AssertionRecord]() + + public init() {} + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + assertions.append( + AssertionRecord( + success: assertion, + message: message, + location: location)) + } +} + +/// Allows you to temporarily replace the current Nimble assertion handler with +/// the one provided for the scope of the closure. +/// +/// Once the closure finishes, then the original Nimble assertion handler is restored. +/// +/// @see AssertionHandler +public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) { + let environment = NimbleEnvironment.activeInstance + let oldRecorder = environment.assertionHandler + let capturer = NMBExceptionCapture(handler: nil, finally: ({ + environment.assertionHandler = oldRecorder + })) + environment.assertionHandler = tempAssertionHandler + capturer.tryBlock { + try! closure() + } +} + +/// Captures expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about expectations +/// that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherFailingExpectations +public func gatherExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler + let recorder = AssertionRecorder() + let handlers: [AssertionHandler] + + if silently { + handlers = [recorder] + } else { + handlers = [recorder, previousRecorder] + } + + let dispatcher = AssertionDispatcher(handlers: handlers) + withAssertionHandler(dispatcher, closure: closure) + return recorder.assertions +} + +/// Captures failed expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about failed +/// expectations that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherExpectations +/// @see raiseException source for an example use case. +public func gatherFailingExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let assertions = gatherExpectations(silently: silently, closure: closure) + return assertions.filter { assertion in + !assertion.success + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..5e1afd5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,187 @@ +import Foundation + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +private func from(objcPredicate: NMBPredicate) -> Predicate { + return Predicate { actualExpression in + let result = objcPredicate.satisfies(({ try! actualExpression.evaluate() }), + location: actualExpression.location) + return result.toSwift() + } +} + +internal struct ObjCMatcherWrapper: Matcher { + let matcher: NMBMatcher + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.matches( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.doesNotMatch( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } +} + +// Equivalent to Expectation, but for Nimble's Objective-C interface +public class NMBExpectation: NSObject { + internal let _actualBlock: () -> NSObject? + internal var _negative: Bool + internal let _file: FileString + internal let _line: UInt + internal var _timeout: TimeInterval = 1.0 + + @objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) { + self._actualBlock = actualBlock + self._negative = negative + self._file = file + self._line = line + } + + private var expectValue: Expectation { + return expect(_file, line: _line) { + self._actualBlock() as NSObject? + } + } + + @objc public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + @objc public var to: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.to(from(objcPredicate: pred)) + } else { + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toNot(from(objcPredicate: pred)) + } else { + self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher)) + } + }) + } + + @objc public var toNotWithDescription: (NMBMatcher, String) -> Void { + 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) + } + }) + } + + @objc public var notTo: (NMBMatcher) -> Void { return toNot } + + @objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + @objc public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventually( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: nil + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + } + }) + } + + @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + if let pred = matcher as? NMBPredicate { + self.expectValue.toEventuallyNot( + from(objcPredicate: pred), + timeout: self._timeout, + description: description + ) + } else { + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + } + }) + } + + @objc public var toNotEventually: (NMBMatcher) -> Void { + return toEventuallyNot + } + + @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { + return toEventuallyNotWithDescription + } + + @objc public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..0288b75 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,83 @@ +import Foundation + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +// swiftlint:disable line_length +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool +// swiftlint:enable line_length + +public class NMBObjCMatcher: NSObject, NMBMatcher { + let _match: MatcherBlock + let _doesNotMatch: MatcherBlock + let canMatchNil: Bool + + public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { + self.canMatchNil = canMatchNil + self._match = matcher + self._doesNotMatch = notMatcher + } + + public convenience init(matcher: @escaping MatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in + return !matcher(actualExpression, failureMessage) + })) + } + + public convenience init(matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, false) + }), notMatcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, true) + })) + } + + private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + do { + if !canMatchNil { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return false + } + } + } catch let error { + failureMessage.actualValue = "an unexpected error thrown: \(error)" + return false + } + return true + } + + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _match( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _doesNotMatch( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..e1b5432 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift @@ -0,0 +1,45 @@ +import Dispatch +import Foundation + +/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this +/// class' existence +internal class NimbleEnvironment { + static var activeInstance: NimbleEnvironment { + get { + let env = Thread.current.threadDictionary["NimbleEnvironment"] + if let env = env as? NimbleEnvironment { + return env + } else { + let newEnv = NimbleEnvironment() + self.activeInstance = newEnv + return newEnv + } + } + set { + Thread.current.threadDictionary["NimbleEnvironment"] = newValue + } + } + + // TODO: eventually migrate the global to this environment value + var assertionHandler: AssertionHandler { + get { return NimbleAssertionHandler } + set { NimbleAssertionHandler = newValue } + } + + var suppressTVOSAssertionWarning: Bool = false + var awaiter: Awaiter + + init() { + let timeoutQueue: DispatchQueue + if #available(OSX 10.10, *) { + timeoutQueue = DispatchQueue.global(qos: .userInitiated) + } else { + timeoutQueue = DispatchQueue.global(priority: .high) + } + + awaiter = Awaiter( + waitLock: AssertionWaitLock(), + asyncQueue: .main, + timeoutQueue: timeoutQueue) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..c8d32ad --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,92 @@ +import Foundation +import XCTest + +/// Default handler for Nimble. This assertion handler passes failures along to +/// XCTest. +public class NimbleXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + recordFailure("\(message.stringValue)\n", location: location) + } + } +} + +/// Alternative handler for Nimble. This assertion handler passes failures along +/// to XCTest by attempting to reduce the failure message size. +public class NimbleShortXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + let msg: String + if let actual = message.actualValue { + msg = "got: \(actual) \(message.postfixActual)" + } else { + msg = "expected \(message.to) \(message.postfixMessage)" + } + recordFailure("\(msg)\n", location: location) + } + } +} + +/// Fallback handler in case XCTest is unavailable. This assertion handler will abort +/// the program if it is invoked. +class NimbleXCTestUnavailableHandler: AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") + } +} + +#if !SWIFT_PACKAGE +/// Helper class providing access to the currently executing XCTestCase instance, if any +@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { + @objc static let sharedInstance = CurrentTestCaseTracker() + + private(set) var currentTestCase: XCTestCase? + + private var stashed_swift_reportFatalErrorsToDebugger: Bool = false + + @objc func testCaseWillStart(_ testCase: XCTestCase) { + #if swift(>=3.2) + stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger + _swift_reportFatalErrorsToDebugger = false + #endif + + currentTestCase = testCase + } + + @objc func testCaseDidFinish(_ testCase: XCTestCase) { + currentTestCase = nil + + #if swift(>=3.2) + _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger + #endif + } +} +#endif + +func isXCTestAvailable() -> Bool { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // XCTest is weakly linked and so may not be present + return NSClassFromString("XCTestCase") != nil +#else + return true +#endif +} + +private func recordFailure(_ message: String, location: SourceLocation) { +#if SWIFT_PACKAGE + XCTFail("\(message)", file: location.file, line: location.line) +#else + if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { + #if swift(>=4) + let line = Int(location.line) + #else + let line = location.line + #endif + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..8f8d360 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) +// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy +class NSException {} +#endif + +// NOTE: This file is not intended to be included in the Xcode project. It +// is picked up by the Swift Package Manager during its build process. + +/// A dummy reimplementation of the `NMBExceptionCapture` class to serve +/// as a stand-in for build and runtime environments that don't support +/// Objective C. +internal class ExceptionCapture { + let finally: (() -> Void)? + + init(handler: ((NSException) -> Void)?, finally: (() -> Void)?) { + self.finally = finally + } + + func tryBlock(_ unsafeBlock: (() -> Void)) { + // We have no way of handling Objective C exceptions in Swift, + // so we just go ahead and run the unsafeBlock as-is + unsafeBlock() + + finally?() + } +} + +/// Compatibility with the actual Objective-C implementation +typealias NMBExceptionCapture = ExceptionCapture diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..e874136 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,116 @@ +import Dispatch +import Foundation + +private enum ErrorResult { + case exception(NSException) + case error(Error) + case none +} + +/// Only classes, protocols, methods, properties, and subscript declarations can be +/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style +/// asynchronous waiting logic so that it may be called from Objective-C and Swift. +internal class NMBWait: NSObject { +// About these kind of lines, `@objc` attributes are only required for Objective-C +// support, so that should be conditional on Darwin platforms and normal Xcode builds +// (non-SwiftPM builds). +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#else + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } +#endif + + // Using a throwable closure makes this method not objc compatible. + internal class func throwableUntil( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) throws -> Void) { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + // swiftlint:disable:next line_length + let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in + DispatchQueue.main.async { + let capture = NMBExceptionCapture( + handler: ({ exception in + done(.exception(exception)) + }), + finally: ({ }) + ) + capture.tryBlock { + do { + try action { + done(.none) + } + } catch let e { + done(.error(e)) + } + } + } + }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line) + + switch result { + case .incomplete: internalError("Reached .incomplete state for waitUntil(...).") + case .blockedRunLoop: + 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) + case let .raisedException(exception): + fail("Unexpected exception raised: \(exception)") + case let .errorThrown(error): + fail("Unexpected error thrown: \(error)") + case .completed(.exception(let exception)): + fail("Unexpected exception raised: \(exception)") + case .completed(.error(let error)): + fail("Unexpected error thrown: \(error)") + case .completed(.none): // success + break + } + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#else + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } +#endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> 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." +} + +/// Wait asynchronously until the done closure is called or the timeout has been reached. +/// +/// @discussion +/// Call the done() closure to indicate the waiting has completed. +/// +/// 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) { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..e49bb0c --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1,64 @@ +import Foundation + +/// Make an expectation on a given actual value. The value given is lazily evaluated. +public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { + 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: @escaping () throws -> T?) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Always fails the test with a message and a specified location. +public func fail(_ message: String, location: SourceLocation) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(false, message: FailureMessage(stringValue: message), location: location) +} + +/// Always fails the test with a message. +public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { + fail(message, location: SourceLocation(file: file, line: line)) +} + +/// Always fails the test. +public func fail(_ file: FileString = #file, line: UInt = #line) { + fail("fail() always fails", file: file, line: line) +} + +/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts +internal func nimblePrecondition( + _ expr: @autoclosure() -> Bool, + _ name: @autoclosure() -> String, + _ message: @autoclosure() -> String, + file: StaticString = #file, + line: UInt = #line) { + let result = expr() + if !result { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let e = NSException( + name: NSExceptionName(name()), + reason: message(), + userInfo: nil) + e.raise() +#else + preconditionFailure("\(name()) - \(message())", file: file, line: line) +#endif + } +} + +internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { + fatalError( + "Nimble Bug Found: \(msg) at \(file):\(line).\n" + + "Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " + + "code snippet that caused this error." + ) +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..e3f616a --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,132 @@ +import Foundation + +// Deprecated +internal func expressionMatches(_ expression: Expression, matcher: U, to: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let pass = try matcher.matches(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +// Deprecated +internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = toNot + do { + let pass = try matcher.doesNotMatch(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { + func run() -> (Bool, FailureMessage) { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let result = try predicate.satisfies(expression) + result.message.update(failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (result.toBoolean(expectation: style), msg) + } catch let error { + msg.stringValue = "unexpected error thrown: <\(error)>" + return (false, msg) + } + } + + var result: (Bool, FailureMessage) = (false, FailureMessage()) + if captureExceptions { + let capture = NMBExceptionCapture(handler: ({ exception -> Void in + let msg = FailureMessage() + msg.stringValue = "unexpected exception raised: \(exception)" + result = (false, msg) + }), finally: nil) + capture.tryBlock { + result = run() + } + } else { + result = run() + } + + return result +} + +public struct Expectation { + + public let expression: Expression + + public func verify(_ pass: Bool, _ message: FailureMessage) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(pass, message: message, location: expression.location) + } + + ////////////////// OLD API ///////////////////// + + /// DEPRECATED: Tests the actual value using a matcher to match. + public func to(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionMatches(expression, matcher: matcher, to: "to", description: description) + verify(pass, msg) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + 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) + } + + /// DEPRECATED: Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + toNot(matcher, description: description) + } + + ////////////////// NEW API ///////////////////// + + /// Tests the actual value using a matcher to match. + public func to(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ predicate: Predicate, description: String? = nil) { + let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ predicate: Predicate, description: String? = nil) { + toNot(predicate, description: description) + } + + // see: + // - AsyncMatcherWrapper for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift new file mode 100644 index 0000000..992ee0e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/ExpectationMessage.swift @@ -0,0 +1,262 @@ +import Foundation + +public indirect enum ExpectationMessage { + // --- Primary Expectations --- + /// includes actual value in output ("expected to , got ") + case expectedActualValueTo(/* message: */ String) + /// uses a custom actual value string in output ("expected to , got ") + case expectedCustomValueTo(/* message: */ String, /* actual: */ String) + /// excludes actual value in output ("expected to ") + case expectedTo(/* message: */ String) + /// allows any free-form message ("") + case fail(/* message: */ String) + + // --- Composite Expectations --- + // Generally, you'll want the methods, appended(message:) and appended(details:) instead. + + /// Not Fully Implemented Yet. + case prepends(/* Prepended Message */ String, ExpectationMessage) + + /// appends after an existing message (" (use beNil() to match nils)") + case appends(ExpectationMessage, /* Appended Message */ String) + + /// provides long-form multi-line explainations ("\n\n") + case details(ExpectationMessage, String) + + internal var sampleMessage: String { + let asStr = toString(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. + public var expectedMessage: String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return msg + case let .expectedActualValueTo(msg): + return msg + case let .expectedCustomValueTo(msg, _): + return msg + case let .prepends(_, expectation): + return expectation.expectedMessage + case let .appends(expectation, msg): + return "\(expectation.expectedMessage)\(msg)" + case let .details(expectation, _): + return expectation.expectedMessage + } + } + + /// Appends a message after the primary expectation message + public func appended(message: String) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo, .appends, .prepends: + return .appends(self, message) + case let .details(expectation, msg): + return .details(expectation.appended(message: message), msg) + } + } + + /// Appends a message hinting to use beNil() for when the actual value given was nil. + public func appendedBeNilHint() -> ExpectationMessage { + return appended(message: " (use beNil() to match nils)") + } + + /// Appends a detailed (aka - multiline) message after the primary expectation message + /// Detailed messages will be placed after .appended(message:) calls. + public func appended(details: String) -> ExpectationMessage { + return .details(self, details) + } + + internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + switch self { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(self) + case let .prepends(msg, expectation): + return .prepends(msg, expectation.visitLeafs(f)) + case let .appends(expectation, msg): + return .appends(expectation.visitLeafs(f), msg) + case let .details(expectation, msg): + return .details(expectation.visitLeafs(f), msg) + } + } + + /// Replaces a primary expectation with one returned by f. Preserves all composite expectations + /// that were built upon it (aka - all appended(message:) and appended(details:). + public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo: + return f(msg) + default: + return msg + } + } + return visitLeafs(walk) + } + + /// Wraps a primary expectation with text before and after it. + /// Alias to prepended(message: before).appended(message: after) + public func wrappedExpectation(before: String, after: String) -> ExpectationMessage { + return prepended(expectation: before).appended(message: after) + } + + /// Prepends a message by modifying the primary expectation + public func prepended(expectation message: String) -> ExpectationMessage { + func walk(_ msg: ExpectationMessage) -> ExpectationMessage { + switch msg { + case let .expectedTo(msg): + return .expectedTo(message + msg) + case let .expectedActualValueTo(msg): + return .expectedActualValueTo(message + msg) + case let .expectedCustomValueTo(msg, actual): + return .expectedCustomValueTo(message + msg, actual) + default: + return msg.visitLeafs(walk) + } + } + return visitLeafs(walk) + } + + // TODO: test & verify correct behavior + internal func prepended(message: String) -> ExpectationMessage { + return .prepends(message, self) + } + + /// Converts the tree of ExpectationMessages into a final built string. + public func toString(actual: String, expected: String = "expected", to: String = "to") -> String { + switch self { + case let .fail(msg): + return msg + case let .expectedTo(msg): + return "\(expected) \(to) \(msg)" + case let .expectedActualValueTo(msg): + return "\(expected) \(to) \(msg), got \(actual)" + case let .expectedCustomValueTo(msg, actual): + return "\(expected) \(to) \(msg), got \(actual)" + case let .prepends(msg, expectation): + return "\(msg)\(expectation.toString(actual: actual, expected: expected, to: to))" + case let .appends(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\(msg)" + case let .details(expectation, msg): + return "\(expectation.toString(actual: actual, expected: expected, to: to))\n\n\(msg)" + } + } + + // Backwards compatibility: converts ExpectationMessage tree to FailureMessage + internal func update(failureMessage: FailureMessage) { + switch self { + case let .fail(msg): + failureMessage.stringValue = msg + case let .expectedTo(msg): + failureMessage.actualValue = nil + failureMessage.postfixMessage = msg + case let .expectedActualValueTo(msg): + failureMessage.postfixMessage = msg + case let .expectedCustomValueTo(msg, actual): + failureMessage.postfixMessage = msg + failureMessage.actualValue = actual + case let .prepends(msg, expectation): + expectation.update(failureMessage: failureMessage) + if let desc = failureMessage.userDescription { + failureMessage.userDescription = "\(msg)\(desc)" + } else { + failureMessage.userDescription = msg + } + case let .appends(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendMessage(msg) + case let .details(expectation, msg): + expectation.update(failureMessage: failureMessage) + failureMessage.appendDetails(msg) + } + } +} + +extension FailureMessage { + internal func toExpectationMessage() -> ExpectationMessage { + let defaultMsg = FailureMessage() + if expected != defaultMsg.expected || _stringValueOverride != nil { + return .fail(stringValue) + } + + var msg: ExpectationMessage = .fail(userDescription ?? "") + if actualValue != "" && actualValue != nil { + msg = .expectedCustomValueTo(postfixMessage, actualValue ?? "") + } else if postfixMessage != defaultMsg.postfixMessage { + if actualValue == nil { + msg = .expectedTo(postfixMessage) + } else { + msg = .expectedActualValueTo(postfixMessage) + } + } + if postfixActual != defaultMsg.postfixActual { + msg = .appends(msg, postfixActual) + } + if let m = extendedMessage { + msg = .details(msg, m) + } + return msg + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +public class NMBExpectationMessage: NSObject { + private let msg: ExpectationMessage + + internal init(swift msg: ExpectationMessage) { + self.msg = msg + } + + public init(expectedTo message: String) { + self.msg = .expectedTo(message) + } + public init(expectedActualValueTo message: String) { + self.msg = .expectedActualValueTo(message) + } + + public init(expectedActualValueTo message: String, customActualValue actual: String) { + self.msg = .expectedCustomValueTo(message, actual) + } + + public init(fail message: String) { + self.msg = .fail(message) + } + + public init(prepend message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(appendedMessage message: String, child: NMBExpectationMessage) { + self.msg = .appends(child.msg, message) + } + + public init(prependedMessage message: String, child: NMBExpectationMessage) { + self.msg = .prepends(message, child.msg) + } + + public init(details message: String, child: NMBExpectationMessage) { + self.msg = .details(child.msg, message) + } + + public func appendedBeNilHint() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: msg.appendedBeNilHint()) + } + + public func toSwift() -> ExpectationMessage { return self.msg } +} + +extension ExpectationMessage { + func toObjectiveC() -> NMBExpectationMessage { + return NMBExpectationMessage(swift: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..5a233fd --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,99 @@ +import Foundation + +// Memoizes the given closure, only calling the passed +// closure once; even if repeat calls to the returned closure +internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { + var cache: T? + return ({ withoutCaching in + if withoutCaching || cache == nil { + cache = try closure() + } + return cache! + }) +} + +/// Expression represents the closure of the value inside expect(...). +/// Expressions are memoized by default. This makes them safe to call +/// evaluate() multiple times without causing a re-evaluation of the underlying +/// closure. +/// +/// @warning Since the closure can be any code, Objective-C code may choose +/// to raise an exception. Currently, Expression does not memoize +/// exception raising. +/// +/// This provides a common consumable API for matchers to utilize to allow +/// Nimble to change internals to how the captured closure is managed. +public struct Expression { + internal let _expression: (Bool) throws -> T? + internal let _withoutCaching: Bool + public let location: SourceLocation + public let isClosure: Bool + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. The expression is memoized. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { + self._expression = memoizedClosure(expression) + self.location = location + self._withoutCaching = false + self.isClosure = isClosure + } + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param withoutCaching Indicates if the struct should memoize the given + /// closure's result. Subsequent evaluate() calls will + /// not call the given closure if this is true. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { + self._expression = memoizedExpression + self.location = location + self._withoutCaching = withoutCaching + self.isClosure = isClosure + } + + /// Returns a new Expression from the given expression. Identical to a map() + /// on this type. This should be used only to typecast the Expression's + /// closure value. + /// + /// The returned expression will preserve location and isClosure. + /// + /// @param block The block that can cast the current Expression value to a + /// new type. + public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { + return Expression( + expression: ({ try block(self.evaluate()) }), + location: self.location, + isClosure: self.isClosure + ) + } + + public func evaluate() throws -> T? { + return try self._expression(_withoutCaching) + } + + public func withoutCaching() -> Expression { + return Expression( + memoizedExpression: self._expression, + location: location, + withoutCaching: true, + isClosure: isClosure + ) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..2bc57eb --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,92 @@ +import Foundation + +/// Encapsulates the failure message that matchers can report to the end user. +/// +/// This is shared state between Nimble and matchers that mutate this value. +public class FailureMessage: NSObject { + public var expected: String = "expected" + public var actualValue: String? = "" // empty string -> use default; nil -> exclude + public var to: String = "to" + public var postfixMessage: String = "match" + public var postfixActual: String = "" + /// An optional message that will be appended as a new line and provides additional details + /// about the failure. This message will only be visible in the issue navigator / in logs but + /// not directly in the source editor since only a single line is presented there. + public var extendedMessage: String? + public var userDescription: String? + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + internal var hasOverriddenStringValue: Bool { + return _stringValueOverride != nil + } + + public override init() { + } + + public init(stringValue: String) { + _stringValueOverride = stringValue + } + + internal func stripNewlines(_ str: String) -> String { + let whitespaces = CharacterSet.whitespacesAndNewlines + return str + .components(separatedBy: "\n") + .map { line in line.trimmingCharacters(in: whitespaces) } + .joined(separator: "") + } + + internal func computeStringValue() -> String { + var value = "\(expected) \(to) \(postfixMessage)" + if let actualValue = actualValue { + value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" + } + value = stripNewlines(value) + + if let extendedMessage = extendedMessage { + value += "\n\(stripNewlines(extendedMessage))" + } + + if let userDescription = userDescription { + return "\(userDescription)\n\(value)" + } + + return value + } + + internal func appendMessage(_ msg: String) { + if hasOverriddenStringValue { + stringValue += "\(msg)" + } else if actualValue != nil { + postfixActual += msg + } else { + postfixMessage += msg + } + } + + internal func appendDetails(_ msg: String) { + if hasOverriddenStringValue { + if let desc = userDescription { + stringValue = "\(desc)\n\(stringValue)" + } + stringValue += "\n\(msg)" + } else { + if let desc = userDescription { + userDescription = desc + } + extendedMessage = msg + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 Jeff Hui. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..8affa62 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,121 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) throws -> Bool) -> Predicate + where U: Sequence, T == U.Iterator.Element { + let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in + return PredicateStatus(bool: try passFunc(try actualExpression.evaluate())) + } + return createPredicate(matcher) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate + 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(_ elementMatcher: M) -> Predicate + where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType { + return createPredicate(elementMatcher.predicate) +} + +public func allPass(_ elementPredicate: Predicate) -> Predicate + where S: Sequence { + return createPredicate(elementPredicate) +} + +private func createPredicate(_ elementMatcher: Predicate) -> Predicate + 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) + } + } + failure = failure.replacedExpectation({ expectation in + return .expectedTo(expectation.expectedMessage) + }) + return PredicateResult(status: .matches, message: failure) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate { + return NMBPredicate { actualExpression in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + var generator = NSFastEnumerationIterator(value) + while let obj = generator.next() { + if let nsObject = obj as? NSObject { + nsObjects.append(nsObject) + } else { + collectionIsUsable = false + break + } + } + } else { + collectionIsUsable = false + } + + if !collectionIsUsable { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + // swiftlint:disable:next line_length + fail: "allPass can only be used with types which implement NSFastEnumeration (NSArray, NSSet, ...), and whose elements subclass NSObject, got <\(actualValue?.description ?? "nil")>" + ) + ) + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in + if let predicate = matcher as? NMBPredicate { + return predicate.satisfies(({ try! expr.evaluate() }), location: expr.location).toSwift() + } else { + let failureMessage = FailureMessage() + let result = matcher.matches( + ({ try! expr.evaluate() }), + failureMessage: failureMessage, + location: expr.location + ) + let expectationMsg = failureMessage.toExpectationMessage() + return PredicateResult( + bool: result, + message: expectationMsg + ) + } + }) + return try! pred.satisfies(expr).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..3cba8b0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,236 @@ +import Foundation + +/// 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: TimeInterval = 1 + public static var PollInterval: TimeInterval = 0.01 +} + +private func async(style: ExpectationStyle, predicate: Predicate, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate { + return Predicate { actualExpression in + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).\(fnName)(...)" + var lastPredicateResult: PredicateResult? + let result = pollBlock( + pollInterval: poll, + timeoutInterval: timeout, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + lastPredicateResult = try predicate.satisfies(uncachedExpression) + return lastPredicateResult!.toBoolean(expectation: style) + } + switch result { + case .completed: return lastPredicateResult! + case .timedOut: return PredicateResult(status: .fail, message: lastPredicateResult!.message) + case let .errorThrown(error): + return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + case let .raisedException(exception): + return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) + case .blockedRunLoop: + // swiftlint:disable:next line_length + return PredicateResult(status: .fail, message: lastPredicateResult!.message.appended(message: " (timed out, but main thread was unresponsive).")) + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } +} + +// Deprecated +internal struct AsyncMatcherWrapper: Matcher + where U: Matcher, U.ValueType == T { + let fullMatcher: U + let timeoutInterval: TimeInterval + let pollInterval: TimeInterval + + init(fullMatcher: U, timeoutInterval: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval) { + self.fullMatcher = fullMatcher + self.timeoutInterval = timeoutInterval + self.pollInterval = pollInterval + } + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).toEventually(...)" + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + try self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: "expect(...).toEventuallyNot(...)") { + try self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.stringValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventuallyNot(...).") + } + } +} + +private let toEventuallyRequiresClosureError = FailureMessage( + // swiftlint:disable:next line_length + stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function" +) + +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toMatch, + async(style: .toMatch, predicate: predicate, timeout: timeout, poll: pollInterval, fnName: "toEventually"), + to: "to eventually", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) + + let (pass, msg) = execute( + expression, + .toNotMatch, + async( + style: .toNotMatch, + predicate: predicate, + timeout: timeout, + poll: pollInterval, + fnName: "toEventuallyNot" + ), + to: "to eventually not", + description: description, + captureExceptions: false + ) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + } +} + +// Deprecated +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionMatches( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + to: "to eventually", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionDoesNotMatch( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + toNot: "to eventually not", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @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(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..ac9d723 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,68 @@ +import Foundation + +private func matcherMessage(forType expectedType: T.Type) -> String { + return "be a kind of \(String(describing: expectedType))" +} +private func matcherMessage(forClass expectedClass: AnyClass) -> String { + return "be a kind of \(String(describing: expectedClass))" +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "") + return PredicateResult(status: .fail, message: message) + } + message = .expectedCustomValueTo( + "be a kind of \(String(describing: expectedType))", + "<\(String(describing: type(of: validInstance))) instance>" + ) + + return PredicateResult( + bool: validInstance is T, + message: message + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// 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 +public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { + return Predicate.define { actualExpression in + let message: ExpectationMessage + let status: PredicateStatus + + let instance = try actualExpression.evaluate() + if let validInstance = instance { + status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "<\(String(describing: type(of: validInstance))) instance>" + ) + } else { + status = .fail + message = .expectedCustomValueTo( + matcherMessage(forClass: expectedClass), + "" + ) + } + + return PredicateResult(status: status, message: message) + } +} + +extension NMBObjCMatcher { + @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try! beAKindOf(expected).satisfies(actualExpression).toObjectiveC() + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..5e2c850 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,56 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. +public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedType))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + return PredicateResult( + status: .doesNotMatch, + message: .expectedActualValueTo(errorMessage) + ) + } + + let actualString = "<\(String(describing: type(of: validInstance))) instance>" + + return PredicateResult( + status: PredicateStatus(bool: type(of: validInstance) == expectedType), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAKindOf if you want to match against subclasses +public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { + let errorMessage = "be an instance of \(String(describing: expectedClass))" + return Predicate.define { actualExpression in + let instance = try actualExpression.evaluate() + let actualString: String + if let validInstance = instance { + actualString = "<\(String(describing: type(of: validInstance))) instance>" + } else { + actualString = "" + } + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let matches = instance != nil && instance!.isMember(of: expectedClass) + #else + let matches = instance != nil && type(of: instance!) == expectedClass + #endif + return PredicateResult( + status: PredicateStatus(bool: matches), + message: .expectedCustomValueTo(errorMessage, actualString) + ) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try! beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..34fa1b8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,126 @@ +import Foundation + +public let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, + expectedValue: NMBDoubleConvertible, + delta: Double) + -> PredicateResult { + let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + return PredicateResult( + bool: actualValue != nil && + abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta, + message: .expectedCustomValueTo(errorMessage, "<\(stringify(actualValue))>") + ) +} + +/// 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: Double, within delta: Double = DefaultDelta) -> Predicate { + 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 { + return Predicate.define { actualExpression in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + 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) + return try! matcher.matches(expr, failureMessage: failureMessage) + } + + @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) + return try! matcher.doesNotMatch(expr, failureMessage: failureMessage) + } + + @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) + } +} +#endif + +public func beCloseTo(_ expectedValues: [Double], within delta: Double = DefaultDelta) -> Predicate<[Double]> { + let errorMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + return Predicate.simple(errorMessage) { actualExpression in + if let actual = try actualExpression.evaluate() { + if actual.count != expectedValues.count { + return .doesNotMatch + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return .doesNotMatch + } + } + return .matches + } + } + return .doesNotMatch + } +} + +// MARK: - Operators + +infix operator ≈ : ComparisonPrecedence + +public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +public 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 +// unexpectantly +precedencegroup PlusMinusOperatorPrecedence { + higherThan: BitwiseShiftPrecedence +} + +infix operator ± : PlusMinusOperatorPrecedence +public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) { + return (expected: lhs, delta: rhs) +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..3cbc15d --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,95 @@ +import Foundation + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return .fail + } + var generator = actualSeq!.makeIterator() + return PredicateStatus(bool: generator.next() == nil) + } +} + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0) + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For NSString instances, it is an empty string. +public func beEmpty() -> Predicate { + return Predicate.simple("be empty") { actualExpression in + let actualString = try actualExpression.evaluate() + return PredicateStatus(bool: actualString == nil || actualString!.length == 0) + } +} + +// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, +// etc, since they conform to Sequence as well as NMBCollection. + +/// 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 { + return Predicate.simple("be empty") { actualExpression in + let actualDictionary = try actualExpression.evaluate() + return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.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 { + return Predicate.simple("be empty") { actualExpression in + let actualArray = try actualExpression.evaluate() + return PredicateStatus(bool: actualArray == nil || actualArray!.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 { + return Predicate.simple("be empty") { actualExpression in + let actual = try actualExpression.evaluate() + return PredicateStatus(bool: actual == nil || actual!.count == 0) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @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) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! beEmpty().satisfies(expr).toObjectiveC() + } else if let actualValue = actualValue { + // swiftlint:disable:next line_length + let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + expectedActualValueTo: badTypeErrorMsg, + customActualValue: "\(String(describing: type(of: actualValue))) type" + ) + ) + } + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() + ) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..4370f19 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> Predicate { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { + let errorMessage = "be greater than <\(stringify(expectedValue))>" + return Predicate.simple(errorMessage) { actualExpression in + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil + && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending + return PredicateStatus(bool: matches) + } +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..55d8e7b --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -0,0 +1,44 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if let actual = actualValue, let expected = expectedValue { + return actual >= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..5732922 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -0,0 +1,53 @@ +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 { + return Predicate.define { actualExpression in + #if os(Linux) + let actual = try actualExpression.evaluate() as? AnyObject + #else + let actual = try actualExpression.evaluate() as AnyObject? + #endif + + let bool: Bool + #if os(Linux) + bool = actual === (expected as? AnyObject) && actual !== nil + #else + bool = actual === (expected as AnyObject?) && actual !== nil + #endif + return PredicateResult( + bool: bool, + message: .expectedCustomValueTo( + "be identical to \(identityAsString(expected))", + "\(identityAsString(actual))" + ) + ) + } +} + +public func === (lhs: Expectation, rhs: Any?) { + lhs.to(beIdenticalTo(rhs)) +} +public func !== (lhs: Expectation, rhs: Any?) { + lhs.toNot(beIdenticalTo(rhs)) +} + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +/// +/// Alias for "beIdenticalTo". +public func be(_ expected: Any?) -> Predicate { + return beIdenticalTo(expected) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let aExpr = actualExpression.cast { $0 as Any? } + return try! beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..8047efd --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual < expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending + return matches + }.requireNonNil +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..f9e9f4e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual <= expected + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + return actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedDescending + }.requireNonNil +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..2b18b4c --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,167 @@ +import Foundation + +extension Int8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int8Value + } +} + +extension UInt8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint8Value + } +} + +extension Int16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int16Value + } +} + +extension UInt16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint16Value + } +} + +extension Int32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int32Value + } +} + +extension UInt32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint32Value + } +} + +extension Int64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int64Value + } +} + +extension UInt64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint64Value + } +} + +extension Float: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).floatValue + } +} + +extension Double: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).doubleValue + } +} + +extension Int: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).intValue + } +} + +extension UInt: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uintValue + } +} + +internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { + return Predicate { actualExpression in + let result = try matcher.satisfies(actualExpression) + return PredicateResult(status: result.status, message: message) + }.requireNonNil +} + +// MARK: beTrue() / beFalse() + +/// A Nimble matcher that succeeds when the actual value is exactly true. +/// This matcher will not match against nils. +public func beTrue() -> Predicate { + return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> Predicate { + return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> Predicate { + return Predicate.simpleNilable("be truthy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == true) + } + + return PredicateStatus(bool: actualValue == (true as T)) + } + return PredicateStatus(bool: actualValue != nil) + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> Predicate { + return Predicate.simpleNilable("be falsy") { actualExpression in + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return PredicateStatus(bool: number.boolValue == false) + } + + return PredicateStatus(bool: actualValue == (false as T)) + } + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beTruthyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTruthy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalsyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalsy().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beTrueMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTrue().matches(expr, failureMessage: failureMessage) + } + } + + @objc public class func beFalseMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalse().matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..a22e0f4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,19 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> Predicate { + return Predicate.simpleNilable("be nil") { actualExpression in + let actualValue = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue == nil) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..a9dbc28 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift @@ -0,0 +1,17 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is Void. +public func beVoid() -> Predicate<()> { + return Predicate.simpleNilable("be void") { actualExpression in + let actualValue: ()? = try actualExpression.evaluate() + return PredicateStatus(bool: actualValue != nil) + } +} + +public func == (lhs: Expectation<()>, rhs: ()) { + lhs.to(beVoid()) +} + +public func != (lhs: Expectation<()>, rhs: ()) { + lhs.toNot(beVoid()) +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..c2ab568 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,60 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's first element +/// is equal to the expected value. +public func beginWith(_ startingElement: T) -> Predicate + where S.Iterator.Element == T { + 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> Predicate { + return Predicate.simple("begin with <\(startingElement)>") { actualExpression in + guard let collection = try actualExpression.evaluate() else { return .fail } + guard collection.count > 0 else { return .doesNotMatch } + #if os(Linux) + guard let collectionValue = collection.object(at: 0) as? NSObject else { + return .fail + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return PredicateStatus(bool: collectionValue.isEqual(startingElement)) + } +} + +/// A Nimble matcher that succeeds when the actual string contains expected substring +/// where the expected substring's location is zero. +public func beginWith(_ startingSubstring: String) -> Predicate { + return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return PredicateStatus(bool: range != nil && range!.lowerBound == actual.startIndex) + } + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! beginWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..f1afb72 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,95 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> Predicate + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + if let actual = try actualExpression.evaluate() { + return items.all { + return actual.contains($0) + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { + let range = actual.range(of: $0) + return range != nil && !range!.isEmpty + } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> Predicate { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { actual.range(of: $0.description).length != 0 } + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> Predicate { + return contain(items) +} + +public func contain(_ items: [Any?]) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + guard let actual = try actualExpression.evaluate() else { return false } + return items.all { item in + return item != nil && actual.contains(item!) + } + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + if let value = actualValue as? NMBContainer { + let expr = Expression(expression: ({ value as NMBContainer }), location: location) + + // A straightforward cast on the array causes this to crash, so we have to cast the individual items + let expectedOptionals: [Any?] = expected.map({ $0 as Any? }) + return try! contain(expectedOptionals).matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! contain(expected as! [String]).matches(expr, failureMessage: failureMessage) + } else if actualValue != nil { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)" + } else { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..ae0d854 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,60 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T { + + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.actualValue = nil + + if predicateDescription == "" { + failureMessage.postfixMessage = "find object in collection that satisfies predicate" + } else { + failureMessage.postfixMessage = "find object in collection \(predicateDescription)" + } + + if let sequence = try actualExpression.evaluate() { + for object in sequence { + if predicate(object) { + return true + } + } + + return false + } + + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + extension NMBObjCMatcher { + @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let value = try! actualExpression.evaluate() + guard let enumeration = value as? NSFastEnumeration else { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + var iterator = NSFastEnumerationIterator(enumeration) + while let item = iterator.next() { + guard let object = item as? NSObject else { + continue + } + + if predicate(object) { + return true + } + } + + failureMessage.actualValue = nil + failureMessage.postfixMessage = "" + failureMessage.to = "to find object in collection that satisfies predicate" + return false + } + } + } +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..a6f9f91 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift @@ -0,0 +1,72 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's last element +/// is equal to the expected value. +public func endWith(_ endingElement: T) -> Predicate + where S.Iterator.Element == T { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + + 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) + + return lastItem == endingElement + } + return false + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + guard let collection = try actualExpression.evaluate() else { return false } + guard collection.count > 0 else { return false } + #if os(Linux) + guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: collection.count - 1) as AnyObject + #endif + + return collectionValue.isEqual(endingElement) + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring +/// where the expected substring's location is the actual string's length minus the +/// expected substring's length. +public func endWith(_ endingSubstring: String) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingSubstring)>" + if let collection = try actualExpression.evaluate() { + return collection.hasSuffix(endingSubstring) + } + return false + }.requireNonNil +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if (actual as? String) != nil { + let expr = actualExpression.cast { $0 as? String } + return try! endWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! endWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..ab457ca --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,220 @@ +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. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: T?) -> Predicate { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult(status: PredicateStatus(bool: matches), message: msg) + } +} + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: [T: C]?) -> Predicate<[T: C]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult(status: .fail, message: msg) + } + return PredicateResult( + status: PredicateStatus(bool: expectedValue! == actualValue!), + message: msg + ) + } +} + +/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection. +/// Items must implement the Equatable protocol. +public func equal(_ expectedValue: [T]?) -> Predicate<[T]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil && actualValue != nil { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + return PredicateResult( + status: .fail, + message: msg + ) + } + return PredicateResult( + bool: expectedValue! == actualValue!, + message: msg + ) + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { + return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in + if let actualValue = try actualExpression.evaluate() { + let doesNotMatch = PredicateResult( + status: .doesNotMatch, + message: msg + ) + + if expectedValue.count != actualValue.count { + return doesNotMatch + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return doesNotMatch + } else if item != nil && otherItem == nil { + return doesNotMatch + } else if item! != otherItem! { + return doesNotMatch + } + } + + return PredicateResult( + status: .matches, + message: msg + ) + } else { + return PredicateResult( + status: .fail, + message: msg.appendedBeNilHint() + ) + } + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { stringify($0) }) +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> Predicate> { + return equal(expectedValue, stringify: { + if let set = $0 { + return stringify(Array(set).sorted { $0 < $1 }) + } else { + return "nil" + } + }) +} + +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { + return Predicate { actualExpression in + var errorMessage: ExpectationMessage = + .expectedActualValueTo("equal <\(stringify(expectedValue))>") + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + errorMessage = .expectedCustomValueTo( + "equal <\(stringify(expectedValue))>", + "<\(stringify(actualValue))>" + ) + + if expectedValue == actualValue { + return PredicateResult( + status: .matches, + message: errorMessage + ) + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>") + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") + } + return PredicateResult( + status: .doesNotMatch, + message: errorMessage + ) + } + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } else { + return PredicateResult( + status: .fail, + message: errorMessage.appendedBeNilHint() + ) + } + } +} + +public func ==(lhs: Expectation, rhs: T?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation, rhs: T?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.toNot(equal(rhs)) +} + +public func == (lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func != (lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.toNot(equal(rhs)) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + return NMBPredicate { actualExpression in + return try! equal(expected).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..93335a8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,59 @@ +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. +// The representation of the collection content is provided in a new line as an `extendedMessage`. + +/// A Nimble matcher that succeeds when the actual Collection's count equals +/// the expected value +public func haveCount(_ expectedValue: T.IndexDistance) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + // swiftlint:disable:next line_length + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage 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) + return try! haveCount(expected.intValue).matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable" + failureMessage.actualValue = "\(String(describing: type(of: actualValue)))" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..96e7a82 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift @@ -0,0 +1,29 @@ +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 { + 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) + } + } + + return .fail + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +extension NMBObjCMatcher { + @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBPredicate { actualExpression in + let actual = actualExpression.cast { $0 as? String } + return try! match(expected.description).satisfies(actual).toObjectiveC() + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..9c86fb7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,58 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +public func matchError(_ error: T) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + } + return matches + }.requireNonNil +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError( + failureMessage, + postfixMessageVerb: "match", + actualError: actualError, + errorType: errorType + ) + var matches = false + if actualError as? T != nil { + matches = true + } + return matches + }.requireNonNil +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..abcafa9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,85 @@ +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil +/// values are received in an expectation. +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct MatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try matcher(actualExpression, failureMessage) + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try !matcher(actualExpression, failureMessage) + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} + +/// DEPRECATED: A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// Unlike MatcherFunc, this will always fail if an expectation contains nil. +/// This applies regardless of using to() or toNot(). +/// +/// You may use this when implementing your own custom matchers. +/// +/// 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") +public struct NonNilMatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try !matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return true + } + return false + } + + /// 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. + public var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..6f8f103 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,154 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +@available(*, deprecated, message: "Use Predicate instead") +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +extension Matcher { + var predicate: Predicate { + return Predicate.fromDeprecatedMatcher(self) + } + + var toClosure: (Expression, FailureMessage, Bool) throws -> Bool { + return ({ expr, msg, expectedResult in + if expectedResult { + return try self.matches(expr, failureMessage: msg) + } else { + return try self.doesNotMatch(expr, failureMessage: msg) + } + }) + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +/// Objective-C interface to the Swift variant of Matcher. +@objc public protocol NMBMatcher { + func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool + func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool +} +#endif + +/// Protocol for types that support contain() matcher. +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a +//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet +#endif + +extension NSArray: NMBContainer {} +extension NSSet: NMBContainer {} + +/// Protocol for types that support only beEmpty(), haveCount() matchers +public protocol NMBCollection { + var count: Int { get } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable: NMBCollection {} +#endif + +extension NSSet: NMBCollection {} +extension NSIndexSet: NMBCollection {} +extension NSDictionary: NMBCollection {} + +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} + +extension NSArray: NMBOrderedCollection {} + +public protocol NMBDoubleConvertible { + var doubleValue: CDouble { get } +} + +extension Double: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self + } +} + +extension Float: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension CGFloat: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension NSNumber: NMBDoubleConvertible { +} + +private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.locale = Locale(identifier: "en_US_POSIX") + + return formatter +}() + +extension Date: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension NSDate: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension Date: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: self) + } +} + +extension NSDate: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) + } +} + +/// 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 os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@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 { + return compare(otherObject as! NSNumber) + } +} +extension NSString: NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! String) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..ee886f1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,96 @@ +import Foundation + +// A workaround to SR-6419. +extension NotificationCenter { +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + #if swift(>=4.0) + #if swift(>=4.0.2) + #else + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #elseif swift(>=3.2) + #if swift(>=3.2.2) + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif + #else + // swiftlint:disable:next line_length + func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol { + return addObserver(forName: name, object: obj, queue: queue, usingBlock: block) + } + #endif +#endif +} + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + // swiftlint:disable:next line_length + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil, using: { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + }) + } + + deinit { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + if let token = self.token { + self.notificationCenter.removeObserver(token) + } + #else + if let token = self.token as? AnyObject { + self.notificationCenter.removeObserver(token) + } + #endif + } +} + +private let mainThread = pthread_self() + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = .default) + -> Predicate + where T: Matcher, T.ValueType == [Notification] +{ + _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + collector.startObserving() + var once: Bool = false + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage 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 match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) + if collector.observedNotifications.isEmpty { + failureMessage.actualValue = "no notifications" + } else { + failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" + } + return match + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift new file mode 100644 index 0000000..f812344 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Predicate.swift @@ -0,0 +1,348 @@ +// New Matcher API +// +import Foundation + +/// A Predicate is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate +/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble +/// matcher API. +/// +/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, +/// predicates are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +public struct Predicate { + fileprivate var matcher: (Expression) throws -> PredicateResult + + /// Constructs a predicate that knows how take a given value + public init(_ matcher: @escaping (Expression) throws -> PredicateResult) { + self.matcher = matcher + } + + /// Uses a predicate on a given value to see if it passes the predicate. + /// + /// @param expression The value to run the predicate's logic against + /// @returns A predicate result indicate passing or failing and an associated error message. + public func satisfies(_ expression: Expression) throws -> PredicateResult { + return try matcher(expression) + } +} + +/// Provides convenience helpers to defining predicates +extension Predicate { + /// Like Predicate() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (Expression) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual) + }.requireNonNil + } + + /// 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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + }.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, ExpectationMessage) throws -> PredicateResult) -> Predicate { + return Predicate { actual in + return try matcher(actual, .expectedActualValueTo(msg)) + } + } +} + +extension Predicate { + /// Provides a simple predicate definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the predicate's actual value cannot pass with `nil` given. + public static func simple(_ msg: String, matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + }.requireNonNil + } + + /// Provides a simple predicate definition that provides no control over the predefined + /// 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) throws -> PredicateStatus) -> Predicate { + return Predicate { actual in + return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(msg)) + } + } +} + +// The Expectation style intended for comparison to a PredicateStatus. +public enum ExpectationStyle { + case toMatch, toNotMatch +} + +/// The value that a Predicates return to describe if the given (actual) value matches the +/// predicate. +public struct PredicateResult { + /// Status indicates if the predicate matches, does not match, or fails. + public var status: PredicateStatus + /// The error message that can be displayed if it does not match + public var message: ExpectationMessage + + /// Constructs a new PredicateResult with a given status and error message + public init(status: PredicateStatus, message: ExpectationMessage) { + self.status = status + self.message = message + } + + /// Shorthand to PredicateResult(status: PredicateStatus(bool: bool), message: message) + public init(bool: Bool, message: ExpectationMessage) { + self.status = PredicateStatus(bool: bool) + self.message = message + } + + /// Converts the result to a boolean based on what the expectation intended + public func toBoolean(expectation style: ExpectationStyle) -> Bool { + return status.toBoolean(expectation: style) + } +} + +/// PredicateStatus is a trinary that indicates if a Predicate matches a given value or not +public enum PredicateStatus { + /// Matches indicates if the predicate / matcher passes with the given value + /// + /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. + case matches + /// DoesNotMatch indicates if the predicate / matcher fails with the given value, but *would* + /// succeed if the expectation was inverted. + /// + /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. + case doesNotMatch + /// Fail indicates the predicate will never satisfy with the given value in any case. + /// A perfect example is that most matchers fail whenever given `nil`. + /// + /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. + /// Note: Predicate's `requireNonNil` property will also provide this feature mostly for free. + /// Your predicate will still need to guard against nils, but error messaging will be + /// handled for you. + case fail + + /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). + public init(bool matches: Bool) { + if matches { + self = .matches + } else { + self = .doesNotMatch + } + } + + private func shouldMatch() -> Bool { + switch self { + case .matches: return true + case .doesNotMatch, .fail: return false + } + } + + private func shouldNotMatch() -> Bool { + switch self { + case .doesNotMatch: return true + case .matches, .fail: return false + } + } + + /// Converts the PredicateStatus result to a boolean based on what the expectation intended + internal func toBoolean(expectation style: ExpectationStyle) -> Bool { + if style == .toMatch { + return shouldMatch() + } else { + return shouldNotMatch() + } + } +} + +// Backwards compatibility until Old Matcher API removal +extension Predicate: Matcher { + /// Compatibility layer for old Matcher API, deprecated + public static func fromDeprecatedFullClosure(_ matcher: @escaping (Expression, FailureMessage, Bool) throws -> Bool) -> Predicate { + return Predicate { actual in + let failureMessage = FailureMessage() + let result = try matcher(actual, failureMessage, true) + return PredicateResult( + status: PredicateStatus(bool: result), + message: failureMessage.toExpectationMessage() + ) + } + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Emulates the MatcherFunc API + public static func fromDeprecatedClosure(_ matcher: @escaping (Expression, 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() + ) + } + + } + + /// Compatibility layer for old Matcher API, deprecated. + /// Same as calling .predicate on a MatcherFunc or NonNilMatcherFunc type. + public static func fromDeprecatedMatcher(_ matcher: M) -> Predicate where M: Matcher, M.ValueType == T { + return self.fromDeprecatedFullClosure(matcher.toClosure) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toMatch) + } + + /// Deprecated Matcher API, use satisfies(_:_) instead + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let result = try satisfies(actualExpression) + result.message.update(failureMessage: failureMessage) + return result.toBoolean(expectation: .toNotMatch) + } +} + +extension Predicate { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (Expression, PredicateResult) throws -> PredicateResult) -> Predicate { + return Predicate { actual -> PredicateResult in + let result = try self.satisfies(actual) + return try f(actual, result) + } + } + + /// Returns a new Predicate based on the current one that always fails if nil is given as + /// the actual value. + /// + /// This replaces `NonNilMatcherFunc`. + public var requireNonNil: Predicate { + return after { actual, result in + if try actual.evaluate() == nil { + return PredicateResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +public typealias PredicateBlock = (_ actualExpression: Expression) -> NMBPredicateResult + +public class NMBPredicate: NSObject { + private let predicate: PredicateBlock + + public init(predicate: @escaping PredicateBlock) { + self.predicate = predicate + } + + func satisfies(_ expression: @escaping () -> NSObject?, location: SourceLocation) -> NMBPredicateResult { + let expr = Expression(expression: expression, location: location) + return self.predicate(expr) + } +} + +extension NMBPredicate: NMBMatcher { + public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toMatch) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let result = satisfies(actualBlock, location: location).toSwift() + result.message.update(failureMessage: failureMessage) + return result.status.toBoolean(expectation: .toNotMatch) + } +} + +final public class NMBPredicateResult: NSObject { + public var status: NMBPredicateStatus + public var message: NMBExpectationMessage + + public init(status: NMBPredicateStatus, message: NMBExpectationMessage) { + self.status = status + self.message = message + } + + public init(bool success: Bool, message: NMBExpectationMessage) { + self.status = NMBPredicateStatus.from(bool: success) + self.message = message + } + + public func toSwift() -> PredicateResult { + return PredicateResult(status: status.toSwift(), + message: message.toSwift()) + } +} + +extension PredicateResult { + public func toObjectiveC() -> NMBPredicateResult { + return NMBPredicateResult(status: status.toObjectiveC(), message: message.toObjectiveC()) + } +} + +final public class NMBPredicateStatus: NSObject { + private let status: Int + private init(status: Int) { + self.status = status + } + + public static let matches: NMBPredicateStatus = NMBPredicateStatus(status: 0) + public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1) + public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2) + + public override var hashValue: Int { return self.status.hashValue } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherPredicate = object as? NMBPredicateStatus else { + return false + } + return self.status == otherPredicate.status + } + + public static func from(status: PredicateStatus) -> NMBPredicateStatus { + switch status { + case .matches: return self.matches + case .doesNotMatch: return self.doesNotMatch + case .fail: return self.fail + } + } + + public static func from(bool success: Bool) -> NMBPredicateStatus { + return self.from(status: PredicateStatus(bool: success)) + } + + public func toSwift() -> PredicateStatus { + switch status { + case NMBPredicateStatus.matches.status: return .matches + case NMBPredicateStatus.doesNotMatch.status: return .doesNotMatch + case NMBPredicateStatus.fail.status: return .fail + default: + internalError("Unhandle status for NMBPredicateStatus") + } + } +} + +extension PredicateStatus { + public func toObjectiveC() -> NMBPredicateStatus { + return NMBPredicateStatus.from(status: self) + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..3e7f2df --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,198 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +/// 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( + named: String? = nil, + reason: String? = nil, + userInfo: NSDictionary? = nil, + closure: ((NSException) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var exception: NSException? + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + _ = try! actualExpression.evaluate() + return + } + + setFailureMessageForException( + failureMessage, + exception: exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + return exceptionMatchesNonNilFieldsOrClosure( + exception, + named: named, + reason: reason, + userInfo: userInfo, + closure: closure + ) + } +} + +// swiftlint:disable:next function_parameter_count +internal func setFailureMessageForException( + _ failureMessage: FailureMessage, + exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) { + failureMessage.postfixMessage = "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 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" + } +} + +internal func exceptionMatchesNonNilFieldsOrClosure( + _ exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) -> Bool { + var matches = false + + if let exception = exception { + matches = true + + if let named = named, exception.name.rawValue != named { + matches = false + } + if reason != nil && exception.reason != reason { + matches = false + } + if let userInfo = userInfo, let exceptionUserInfo = exception.userInfo, + (exceptionUserInfo as NSDictionary) != userInfo { + matches = false + } + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(exception) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} + +public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher { + internal var _name: String? + internal var _reason: String? + internal var _userInfo: NSDictionary? + internal var _block: ((NSException) -> Void)? + + internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) { + _name = name + _reason = reason + _userInfo = userInfo + _block = block + } + + @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) + + return try! raiseException( + named: _name, + reason: _reason, + userInfo: _userInfo, + closure: _block + ).matches(expr, failureMessage: failureMessage) + } + + @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( + 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 + ) + }) + } +} + +extension NMBObjCMatcher { + @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift new file mode 100644 index 0000000..6c63a15 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift @@ -0,0 +1,101 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAllOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAllOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = true + for matcher in matchers { + if try matcher.doesNotMatch(actualExpression, failureMessage: failureMessage) { + matches = false + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match all of: " + postfixMessages.componentsJoined(by: ", and ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = true + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toNotMatch) { + matches = false + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match all of: " + postfixMessages.joined(separator: ", and "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match all of: " + postfixMessages.joined(separator: ", and ") + ) + } + + return PredicateResult( + bool: matches, + message: msg + ) + }.requireNonNil +} + +public func && (left: Predicate, right: Predicate) -> Predicate { + return satisfyAllOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAllOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..d02a0ff --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,109 @@ +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(_ matchers: U...) -> Predicate + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers) +} + +/// Deprecated. Please use `satisfyAnyOf(_) -> Predicate` instead. +internal func satisfyAnyOf(_ matchers: [U]) -> Predicate + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = false + for matcher in matchers { + if try matcher.matches(actualExpression, failureMessage: failureMessage) { + matches = true + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match one of: " + postfixMessages.componentsJoined(by: ", or ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + }.predicate +} + +internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { + return Predicate { actualExpression in + var postfixMessages = [String]() + var matches = false + for predicate in predicates { + let result = try predicate.satisfies(actualExpression) + if result.toBoolean(expectation: .toMatch) { + matches = true + } + postfixMessages.append("{\(result.message.expectedMessage)}") + } + + var msg: ExpectationMessage + if let actualValue = try actualExpression.evaluate() { + msg = .expectedCustomValueTo( + "match one of: " + postfixMessages.joined(separator: ", or "), + "\(actualValue)" + ) + } else { + msg = .expectedActualValueTo( + "match one of: " + postfixMessages.joined(separator: ", or ") + ) + } + + return PredicateResult( + status: PredicateStatus(bool: matches), + message: msg + ) + }.requireNonNil +} + +public func || (left: Predicate, right: Predicate) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate { + return satisfyAnyOf(left, right) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +extension NMBObjCMatcher { + @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { + return NMBPredicate { actualExpression in + if matchers.isEmpty { + return NMBPredicateResult( + status: NMBPredicateStatus.fail, + message: NMBExpectationMessage( + fail: "satisfyAnyOf must be called with at least one matcher" + ) + ) + } + + var elementEvaluators = [Predicate]() + for matcher in matchers { + let elementEvaluator = Predicate { expression in + if let predicate = matcher as? NMBPredicate { + // swiftlint:disable:next line_length + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + // swiftlint:disable:next line_length + let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location) + return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) + } + } + + elementEvaluators.append(elementEvaluator) + } + + return try! satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..a530c60 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,56 @@ +import Foundation + +public func throwAssertion() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if arch(x86_64) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + failureMessage.postfixMessage = "throw an assertion" + failureMessage.actualValue = nil + + var succeeded = true + + let caughtException: BadInstructionException? = catchBadInstruction { + #if os(tvOS) + if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { + print() + print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + + "fatal error while using throwAssertion(), please disable 'Debug Executable' " + + "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + + "'Debug Executable'. If you've already done that, suppress this warning " + + "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + + "This is required because the standard methods of catching assertions " + + "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + + "debugger uses is the fallback method for tvOS." + ) + print() + NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true + } + #endif + do { + try actualExpression.evaluate() + } catch let error { + succeeded = false + failureMessage.postfixMessage += "; threw error instead <\(error)>" + } + } + + if !succeeded { + return false + } + + if caughtException == nil { + return false + } + + return true + #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. Mac, iPhone 5s or later simulators). You can silence this error " + + "by placing the test case inside an #if arch(x86_64) or (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) conditional statement") + // swiftlint:disable:previous line_length + #endif + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..872ca5c --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,258 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparison by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + failureMessage.postfixMessage = "throw any error" + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } + return actualError != nil + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { + matches = true + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: error, + errorType: nil, + closure: closure + ) + var matches = false + if let actualError = actualError as? T, error == actualError { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError( + errorType: T.Type, + closure: ((T) -> Void)? = nil) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError( + failureMessage, + actualError: actualError, + error: nil, + errorType: errorType, + closure: closure + ) + var matches = false + if let actualError = actualError { + matches = true + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } else { + matches = (actualError is T) + // The closure expects another ErrorProtocol as argument, so this + // is _supposed_ to fail, so that it becomes more obvious. + if let closure = closure { + let assertions = gatherExpectations { + if let actual = actualError as? T { + closure(actual) + } + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + } + + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// 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 { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// values of the existential type `Error` in the closure. +/// +/// The closure only gets called when an error was thrown. +public func throwError(closure: @escaping ((T) -> Void)) -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + + var matches = false + if let actualError = actualError as? T { + matches = true + + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + return matches + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift new file mode 100644 index 0000000..01369bb --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ToSucceed.swift @@ -0,0 +1,37 @@ +/** + Used by the `toSucceed` matcher. + + This is the return type for the closure. + */ +public enum ToSucceedResult { + case succeeded + case failed(reason: String) +} + +/** + A Nimble matcher that takes in a closure for validation. + + Return `.succeeded` when the validation succeeds. + Return `.failed` with a failure reason when the validation fails. + */ +public func succeed() -> Predicate<() -> ToSucceedResult> { + return Predicate.define { actualExpression in + let optActual = try actualExpression.evaluate() + guard let actual = optActual else { + return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) + } + + switch actual() { + case .succeeded: + return PredicateResult( + bool: true, + message: .expectedCustomValueTo("succeed", "") + ) + case .failed(let reason): + return PredicateResult( + bool: false, + message: .expectedCustomValueTo("succeed", " because <\(reason)>") + ) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..2bbc693 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,13 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#if TARGET_OS_TV + #import "CwlPreconditionTesting_POSIX.h" +#else + #import "CwlPreconditionTesting.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..cb672ad --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,381 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + import CDispatch +#endif + +private let timeoutLeeway = DispatchTimeInterval.milliseconds(1) +private let pollLeeway = DispatchTimeInterval.milliseconds(1) + +/// Stores debugging information about callers +internal struct WaitingInfo: CustomStringConvertible { + let name: String + let file: FileString + let lineNumber: UInt + + var description: String { + return "\(name) at \(file):\(lineNumber)" + } +} + +internal protocol WaitLock { + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) + func releaseWaitingLock() + func isWaitingLocked() -> Bool +} + +internal class AssertionWaitLock: WaitLock { + private var currentWaiter: WaitingInfo? + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let isMainThread = Thread.isMainThread + #else + let isMainThread = _CFIsMainThread() + #endif + nimblePrecondition( + isMainThread, + "InvalidNimbleAPIUsage", + "\(fnName) can only run on the main thread." + ) + nimblePrecondition( + currentWaiter == nil, + "InvalidNimbleAPIUsage", + "Nested async expectations are not allowed to avoid creating flaky tests.\n\n" + + "The call to\n\t\(info)\n" + + "triggered this exception because\n\t\(currentWaiter!)\n" + + "is currently managing the main run loop." + ) + currentWaiter = info + } + + func isWaitingLocked() -> Bool { + return currentWaiter != nil + } + + func releaseWaitingLock() { + currentWaiter = nil + } +} + +internal enum AwaitResult { + /// Incomplete indicates None (aka - this value hasn't been fulfilled yet) + case incomplete + /// TimedOut indicates the result reached its defined timeout limit before returning + case timedOut + /// BlockedRunLoop indicates the main runloop is too busy processing other blocks to trigger + /// the timeout code. + /// + /// This may also mean the async code waiting upon may have never actually ran within the + /// required time because other timers & sources are running on the main run loop. + case blockedRunLoop + /// The async block successfully executed and returned a given result + case completed(T) + /// When a Swift Error is thrown + case errorThrown(Error) + /// When an Objective-C Exception is raised + case raisedException(NSException) + + func isIncomplete() -> Bool { + switch self { + case .incomplete: return true + default: return false + } + } + + func isCompleted() -> Bool { + switch self { + case .completed: return true + default: return false + } + } +} + +/// Holds the resulting value from an asynchronous expectation. +/// This class is thread-safe at receiving an "response" to this promise. +internal class AwaitPromise { + private(set) internal var asyncResult: AwaitResult = .incomplete + private var signal: DispatchSemaphore + + init() { + signal = DispatchSemaphore(value: 1) + } + + deinit { + signal.signal() + } + + /// Resolves the promise with the given result if it has not been resolved. Repeated calls to + /// this method will resolve in a no-op. + /// + /// @returns a Bool that indicates if the async result was accepted or rejected because another + /// value was received first. + func resolveResult(_ result: AwaitResult) -> Bool { + if signal.wait(timeout: .now()) == .success { + self.asyncResult = result + return true + } else { + return false + } + } +} + +internal struct AwaitTrigger { + let timeoutSource: DispatchSourceTimer + let actionSource: DispatchSourceTimer? + let start: () throws -> Void +} + +/// Factory for building fully configured AwaitPromises and waiting for their results. +/// +/// This factory stores all the state for an async expectation so that Await doesn't +/// doesn't have to manage it. +internal class AwaitPromiseBuilder { + let awaiter: Awaiter + let waitLock: WaitLock + let trigger: AwaitTrigger + let promise: AwaitPromise + + internal init( + awaiter: Awaiter, + waitLock: WaitLock, + promise: AwaitPromise, + trigger: AwaitTrigger) { + self.awaiter = awaiter + self.waitLock = waitLock + self.promise = promise + self.trigger = trigger + } + + func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + // = Discussion = + // + // There's a lot of technical decisions here that is useful to elaborate on. This is + // definitely more lower-level than the previous NSRunLoop based implementation. + // + // + // Why Dispatch Source? + // + // + // We're using a dispatch source to have better control of the run loop behavior. + // A timer source gives us deferred-timing control without having to rely as much on + // a run loop's traditional dispatching machinery (eg - NSTimers, DefaultRunLoopMode, etc.) + // which is ripe for getting corrupted by application code. + // + // And unlike dispatch_async(), we can control how likely our code gets prioritized to + // executed (see leeway parameter) + DISPATCH_TIMER_STRICT. + // + // This timer is assumed to run on the HIGH priority queue to ensure it maintains the + // highest priority over normal application / test code when possible. + // + // + // Run Loop Management + // + // In order to properly interrupt the waiting behavior performed by this factory class, + // this timer stops the main run loop to tell the waiter code that the result should be + // checked. + // + // In addition, stopping the run loop is used to halt code executed on the main run loop. + #if swift(>=4.0) + trigger.timeoutSource.schedule( + deadline: DispatchTime.now() + timeoutInterval, + repeating: .never, + leeway: timeoutLeeway + ) + #else + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway + ) + #endif + trigger.timeoutSource.setEventHandler { + guard self.promise.asyncResult.isIncomplete() else { return } + let timedOutSem = DispatchSemaphore(value: 0) + let semTimedOutOrBlocked = DispatchSemaphore(value: 0) + semTimedOutOrBlocked.signal() + let runLoop = CFRunLoopGetMain() + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + let now = DispatchTime.now() + forcefullyAbortTimeout + let didNotTimeOut = timedOutSem.wait(timeout: now) != .success + let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success + if didNotTimeOut && timeoutWasNotTriggered { + if self.promise.resolveResult(.blockedRunLoop) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + return self + } + + /// Blocks for an asynchronous result. + /// + /// @discussion + /// This function must be executed on the main thread and cannot be nested. This is because + /// this function (and it's related methods) coordinate through the main run loop. Tampering + /// with the run loop can cause undesirable behavior. + /// + /// This method will return an AwaitResult in the following cases: + /// + /// - The main run loop is blocked by other operations and the async expectation cannot be + /// be stopped. + /// - The async expectation timed out + /// - The async expectation succeeded + /// - The async expectation raised an unexpected exception (objc) + /// - The async expectation raised an unexpected error (swift) + /// + /// The returned AwaitResult will NEVER be .incomplete. + func wait(_ fnName: String = #function, file: FileString = #file, line: UInt = #line) -> AwaitResult { + waitLock.acquireWaitingLock( + fnName, + file: file, + line: line) + + let capture = NMBExceptionCapture(handler: ({ exception in + _ = self.promise.resolveResult(.raisedException(exception)) + }), finally: ({ + self.waitLock.releaseWaitingLock() + })) + capture.tryBlock { + do { + try self.trigger.start() + } catch let error { + _ = self.promise.resolveResult(.errorThrown(error)) + } + 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) + _ = RunLoop.current.run(mode: .default, before: .distantFuture) + #else + _ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture) + #endif + } + + self.trigger.timeoutSource.cancel() + if let asyncSource = self.trigger.actionSource { + asyncSource.cancel() + } + } + + return promise.asyncResult + } +} + +internal class Awaiter { + let waitLock: WaitLock + let timeoutQueue: DispatchQueue + let asyncQueue: DispatchQueue + + internal init( + waitLock: WaitLock, + asyncQueue: DispatchQueue, + timeoutQueue: DispatchQueue) { + self.waitLock = waitLock + self.asyncQueue = asyncQueue + self.timeoutQueue = timeoutQueue + } + + private func createTimerSource(_ queue: DispatchQueue) -> DispatchSourceTimer { + return DispatchSource.makeTimerSource(flags: .strict, queue: queue) + } + + func performBlock( + file: FileString, + line: UInt, + _ closure: @escaping (@escaping (T) -> Void) throws -> Void + ) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + var completionCount = 0 + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) { + try closure { + completionCount += 1 + if completionCount < 2 { + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } else { + fail("waitUntil(..) expects its completion closure to be only called once", + file: file, line: line) + } + } + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } + + func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + 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))) + #if swift(>=4.0) + asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway) + #else + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + #endif + asyncSource.setEventHandler { + do { + if let result = try closure() { + if promise.resolveResult(.completed(result)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } catch let error { + if promise.resolveResult(.errorThrown(error)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } + asyncSource.resume() + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } +} + +internal func pollBlock( + pollInterval: TimeInterval, + timeoutInterval: TimeInterval, + file: FileString, + line: UInt, + fnName: String = #function, + expression: @escaping () throws -> Bool) -> AwaitResult { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let result = awaiter.poll(pollInterval) { () throws -> Bool? in + if try expression() { + return true + } + return nil + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..074cb20 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,59 @@ +import Foundation + +// Generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + postfixMessageVerb: String = "throw", + actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) { + failureMessage.postfixMessage = "\(postfixMessageVerb) error" + + if let error = error { + failureMessage.postfixMessage += " <\(error)>" + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } + if error == nil && errorType == nil && closure == nil { + failureMessage.postfixMessage = "\(postfixMessageVerb) any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool { + return actualError._domain == expectedError._domain + && actualError._code == expectedError._code +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if closure != nil { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift @@ -0,0 +1,12 @@ +import Foundation + +extension Sequence { + internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool { + for item in self { + if !fn(item) { + return false + } + } + return true + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift @@ -0,0 +1,31 @@ +import Foundation + +// Ideally we would always use `StaticString` as the type for tracking the file name +// that expectations originate from, for consistency with `assert` etc. from the +// stdlib, and because recent versions of the XCTest overlay require `StaticString` +// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we +// have to use `String` instead because StaticString can't be generated from Objective-C +#if SWIFT_PACKAGE +public typealias FileString = StaticString +#else +public typealias FileString = String +#endif + +public final class SourceLocation: NSObject { + public let file: FileString + public let line: UInt + + override init() { + file = "Unknown File" + line = 0 + } + + init(file: FileString, line: UInt) { + self.file = file + self.line = line + } + + override public var description: String { + return "\(file):\(line)" + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..7c4d273 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift @@ -0,0 +1,206 @@ +import Foundation + +internal func identityAsString(_ value: Any?) -> String { + let anyObject: AnyObject? +#if os(Linux) + anyObject = value as? AnyObject +#else + anyObject = value as AnyObject? +#endif + if let value = anyObject { + return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description + } else { + return "nil" + } +} + +internal func arrayAsString(_ items: [T], joiner: String = ", ") -> String { + return items.reduce("") { accum, item in + let prefix = (accum.isEmpty ? "" : joiner) + return accum + prefix + "\(stringify(item))" + } +} + +/// A type with a customized test output text representation. +/// +/// This textual representation is produced when values will be +/// printed in test runs, and may be useful when producing +/// error messages in custom matchers. +/// +/// - SeeAlso: `CustomDebugStringConvertible` +public protocol TestOutputStringConvertible { + var testDescription: String { get } +} + +extension Double: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension Float: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +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 { + case 1: + return NSString(format: "%0.1f", self.doubleValue).description + case 2: + return NSString(format: "%0.2f", self.doubleValue).description + case 3: + return NSString(format: "%0.3f", self.doubleValue).description + default: + return NSString(format: "%0.4f", self.doubleValue).description + } + } + return self.description + } +} + +extension Array: TestOutputStringConvertible { + public var testDescription: String { + let list = self.map(Nimble.stringify).joined(separator: ", ") + return "[\(list)]" + } +} + +extension AnySequence: TestOutputStringConvertible { + public var testDescription: String { + let generator = self.makeIterator() + var strings = [String]() + var value: AnySequence.Iterator.Element? + + repeat { + value = generator.next() + if let value = value { + strings.append(stringify(value)) + } + } while value != nil + + let list = strings.joined(separator: ", ") + return "[\(list)]" + } +} + +extension NSArray: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension NSIndexSet: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension String: TestOutputStringConvertible { + public var testDescription: String { + return self + } +} + +extension Data: TestOutputStringConvertible { + public var testDescription: String { + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16) + return "Data" + #else + return "Data" + #endif + } +} + +/// +/// Returns a string appropriate for displaying in test output +/// from the provided value. +/// +/// - parameter value: A value that will show up in a test's output. +/// +/// - returns: The string that is returned can be +/// customized per type by conforming a type to the `TestOutputStringConvertible` +/// protocol. When stringifying a non-`TestOutputStringConvertible` type, this +/// function will return the value's debug description and then its +/// normal description if available and in that order. Otherwise it +/// will return the result of constructing a string from the value. +/// +/// - SeeAlso: `TestOutputStringConvertible` +public func stringify(_ value: T?) -> String { + guard let value = value else { return "nil" } + + if let value = value as? TestOutputStringConvertible { + return value.testDescription + } + + if let value = value as? CustomDebugStringConvertible { + return value.debugDescription + } + + return String(describing: value) +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +@objc public class NMBStringer: NSObject { + @objc public class func stringify(_ obj: Any?) -> String { + return Nimble.stringify(obj) + } +} +#endif + +// MARK: Collection Type Stringers + +/// Attempts to generate a pretty type string for a given value. If the value is of a Objective-C +/// collection type, or a subclass thereof, (e.g. `NSArray`, `NSDictionary`, etc.). +/// This function will return the type name of the root class of the class cluster for better +/// readability (e.g. `NSArray` instead of `__NSArrayI`). +/// +/// For values that don't have a type of an Objective-C collection, this function returns the +/// default type description. +/// +/// - parameter value: A value that will be used to determine a type name. +/// +/// - returns: The name of the class cluster root class for Objective-C collection types, or the +/// the `dynamicType` of the value for values of any other type. +public func prettyCollectionType(_ value: T) -> String { + switch value { + case is NSArray: + return String(describing: NSArray.self) + case is NSDictionary: + return String(describing: NSDictionary.self) + case is NSSet: + return String(describing: NSSet.self) + case is NSIndexSet: + return String(describing: NSIndexSet.self) + default: + return String(describing: value) + } +} + +/// Returns the type name for a given collection type. This overload is used by Swift +/// collection types. +/// +/// - parameter collection: A Swift `CollectionType` value. +/// +/// - returns: A string representing the `dynamicType` of the value. +public func prettyCollectionType(_ collection: T) -> String { + return String(describing: type(of: collection)) +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..9170541 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,389 @@ +#import + +@class NMBExpectation; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; +@protocol NMBMatcher; + + +NS_ASSUME_NONNULL_BEGIN + + +#define NIMBLE_OVERLOADABLE __attribute__((overloadable)) +#define NIMBLE_EXPORT FOUNDATION_EXPORT +#define NIMBLE_EXPORT_INLINE FOUNDATION_STATIC_INLINE + +#define NIMBLE_VALUE_OF(VAL) ({ \ + __typeof__((VAL)) val = (VAL); \ + [NSValue valueWithBytes:&val objCType:@encode(__typeof__((VAL)))]; \ +}) + +#ifdef NIMBLE_DISABLE_SHORT_SYNTAX +#define NIMBLE_SHORT(PROTO, ORIGINAL) +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) +#else +#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); } +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE NIMBLE_OVERLOADABLE PROTO { return (ORIGINAL); } +#endif + + + +#define DEFINE_NMB_EXPECT_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBExpectation *NMB_expect(TYPE(^actualBlock)(void), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(void), NSString *file, NSUInteger line); + + // overloaded dispatch for nils - expect(nil) + DEFINE_NMB_EXPECT_OVERLOAD(void*, nil) + DEFINE_NMB_EXPECT_OVERLOAD(NSRange, NIMBLE_VALUE_OF(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(float, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(double, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned char, @(actualBlock())) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_NMB_EXPECT_OVERLOAD(BOOL, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char *, @(actualBlock())) + + +#undef DEFINE_NMB_EXPECT_OVERLOAD + + + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line); + + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_equal(TYPE expectedValue) { \ + return NMB_equal((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id equal(TYPE expectedValue), NMB_equal(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_equal(__nullable id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id equal(__nullable id expectedValue), + NMB_equal(expectedValue)); + + // overloaded dispatch for nils - expect(nil) + DEFINE_OVERLOAD(void*__nullable, (id)nil) + DEFINE_OVERLOAD(NSRange, NIMBLE_VALUE_OF(expectedValue)) + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_OVERLOAD(BOOL, @(expectedValue)) + DEFINE_OVERLOAD(char *, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_haveCount(TYPE expectedValue) { \ + return NMB_haveCount((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id haveCount(TYPE expectedValue), \ + NMB_haveCount(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_haveCount(id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id haveCount(id expectedValue), + NMB_haveCount(expectedValue)); + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ + return NMB_beCloseTo((NSNumber *)(EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ + NMB_beCloseTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), + NMB_beCloseTo(expectedValue)); + + // it would be better to only overload float & double, but zero becomes ambigious + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAnInstanceOf(Class expectedClass) { + return NMB_beAnInstanceOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAKindOf(Class expectedClass) { + return NMB_beAKindOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE id beginWith(id itemElementOrSubstring) { + return NMB_beginWith(itemElementOrSubstring); +} + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThan(TYPE expectedValue) { \ + return NMB_beGreaterThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThan(NSNumber *expectedValue) { + return NMB_beGreaterThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beGreaterThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThanOrEqualTo(TYPE expectedValue), \ + NMB_beGreaterThanOrEqualTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beGreaterThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(id beIdenticalTo(id expectedInstance), + NMB_beIdenticalTo(expectedInstance)); + +NIMBLE_EXPORT id NMB_be(id expectedInstance); +NIMBLE_SHORT(id be(id expectedInstance), + NMB_be(expectedInstance)); + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThan(TYPE expectedValue) { \ + return NMB_beLessThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThan(TYPE expectedValue), \ + NMB_beLessThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThan(NSNumber *expectedValue) { + return NMB_beLessThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beLessThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThanOrEqualTo(TYPE expectedValue), \ + NMB_beLessThanOrEqualTo(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beLessThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beTruthy(void); +NIMBLE_SHORT(id beTruthy(void), + NMB_beTruthy()); + +NIMBLE_EXPORT id NMB_beFalsy(void); +NIMBLE_SHORT(id beFalsy(void), + NMB_beFalsy()); + +NIMBLE_EXPORT id NMB_beTrue(void); +NIMBLE_SHORT(id beTrue(void), + NMB_beTrue()); + +NIMBLE_EXPORT id NMB_beFalse(void); +NIMBLE_SHORT(id beFalse(void), + NMB_beFalse()); + +NIMBLE_EXPORT id NMB_beNil(void); +NIMBLE_SHORT(id beNil(void), + NMB_beNil()); + +NIMBLE_EXPORT id NMB_beEmpty(void); +NIMBLE_SHORT(id beEmpty(void), + NMB_beEmpty()); + +NIMBLE_EXPORT id 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 NMB_containElementSatisfying(BOOL(^predicate)(id)); +NIMBLE_SHORT(id containElementSatisfying(BOOL(^predicate)(id)), + NMB_containElementSatisfying(predicate)); + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(id endWith(id itemElementOrSubstring), + NMB_endWith(itemElementOrSubstring)); + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), + NMB_raiseException()); + +NIMBLE_EXPORT id NMB_match(id expectedValue); +NIMBLE_SHORT(id match(id expectedValue), + NMB_match(expectedValue)); + +NIMBLE_EXPORT id NMB_allPass(id matcher); +NIMBLE_SHORT(id allPass(id matcher), + NMB_allPass(matcher)); + +NIMBLE_EXPORT id 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 NMB_satisfyAllOfWithMatchers(id matchers); +#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__]) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__) +#endif + +// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__, +// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout +// and action arguments. See https://github.com/Quick/Quick/pull/185 for details. +typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void))); +typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void))); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line); +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +#define NMB_waitUntilTimeout NMB_waitUntilTimeoutBuilder(@(__FILE__), __LINE__) +#define NMB_waitUntil NMB_waitUntilBuilder(@(__FILE__), __LINE__) + +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define expect(...) NMB_expect(^{ return (__VA_ARGS__); }, @(__FILE__), __LINE__) +#define expectAction(BLOCK) NMB_expectAction((BLOCK), @(__FILE__), __LINE__) +#define failWithMessage(msg) NMB_failWithMessage(msg, @(__FILE__), __LINE__) +#define fail() failWithMessage(@"fail() always fails") + + +#define waitUntilTimeout NMB_waitUntilTimeout +#define waitUntil NMB_waitUntil + +#undef NIMBLE_VALUE_OF + +#endif + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..670415b --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,161 @@ +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(void), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSString *file, NSUInteger line) { + return NMB_expect(^id{ + actualBlock(); + return nil; + }, file, line); +} + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line) { + return [NMBExpectation failWithMessage:msg file:file line:line]; +} + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass) { + return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass) { + return [NMBObjCMatcher beAKindOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001]; +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring) { + return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT id NMB_be(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beTruthy() { + return [NMBObjCMatcher beTruthyMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalsy() { + return [NMBObjCMatcher beFalsyMatcher]; +} + +NIMBLE_EXPORT id NMB_beTrue() { + return [NMBObjCMatcher beTrueMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalse() { + return [NMBObjCMatcher beFalseMatcher]; +} + +NIMBLE_EXPORT id NMB_beNil() { + return [NMBObjCMatcher beNilMatcher]; +} + +NIMBLE_EXPORT id NMB_beEmpty() { + return [NMBObjCMatcher beEmptyMatcher]; +} + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) { + NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; + + if (itemOrSubstring) { + [itemOrSubstringArray addObject:itemOrSubstring]; + + va_list args; + va_start(args, itemOrSubstring); + id next; + while ((next = va_arg(args, id))) { + [itemOrSubstringArray addObject:next]; + } + va_end(args); + } + + return [NMBObjCMatcher containMatcher:itemOrSubstringArray]; +} + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)) { + return [NMBObjCMatcher containElementSatisfyingMatcher:predicate]; +} + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring) { + return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_equal(__nullable id expectedValue) { + return [NMBObjCMatcher equalMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_haveCount(id expectedValue) { + return [NMBObjCMatcher haveCountMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_match(id expectedValue) { + return [NMBObjCMatcher matchMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_allPass(id expectedValue) { + return [NMBObjCMatcher allPassMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAnyOfMatcher:matchers]; +} + +NIMBLE_EXPORT id NMB_satisfyAllOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAllOfMatcher:matchers]; +} + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^ _Nonnull action)(void (^ _Nonnull)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..e6e0272 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h @@ -0,0 +1,11 @@ +#import +#import + +@interface NMBExceptionCapture : NSObject + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..52684b7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m @@ -0,0 +1,35 @@ +#import "NMBExceptionCapture.h" + +@interface NMBExceptionCapture () +@property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); +@property (nonatomic, copy) void(^ _Nullable finally)(void); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..7938bca --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h @@ -0,0 +1,18 @@ +@class NSString; + +/** + * Returns a string appropriate for displaying in test output + * from the provided value. + * + * @param anyObject A value that will show up in a test's output. + * + * @return The string that is returned can be + * customized per type by conforming a type to the `TestOutputStringConvertible` + * protocol. When stringifying a non-`TestOutputStringConvertible` type, this + * function will return the value's debug description and then its + * normal description if available and in that order. Otherwise it + * will return the result of constructing a string from the value. + * + * @see `TestOutputStringConvertible` + */ +extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..31a80d6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,11 @@ +#import "NMBStringify.h" + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..fa5030a --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -0,0 +1,83 @@ +#import +#import + +#if __has_include("Nimble-Swift.h") +#import "Nimble-Swift.h" +#else +#import +#endif + +#pragma mark - Method Swizzling + +/// Swaps the implementations between two instance methods. +/// +/// @param class The class containing `originalSelector`. +/// @param originalSelector Original method to replace. +/// @param replacementSelector Replacement method. +void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method replacementMethod = class_getInstanceMethod(class, replacementSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(replacementMethod), + method_getTypeEncoding(replacementMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + replacementSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, replacementMethod); + } +} + +#pragma mark - Private + +@interface XCTestObservationCenter (Private) +- (void)_addLegacyTestObserver:(id)observer; +@end + +@implementation XCTestObservationCenter (Register) + +/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary +/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early +/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. +/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, +/// falling back to registering after the first normal observer if this private method ever changes. ++ (void)load { + if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { + // Swizzle -_addLegacyTestObserver: + swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); + } else { + // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented + swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); + } +} + +#pragma mark - Replacement Methods + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +- (void)NMB_original__addLegacyTestObserver:(id)observer { + [self NMB_original__addLegacyTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) +- (void)NMB_original_addTestObserver:(id)observer { + [self NMB_original_addTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml new file mode 100644 index 0000000..f003326 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/.swiftlint.yml @@ -0,0 +1,2 @@ +disabled_rules: + - line_length diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift @@ -0,0 +1,37 @@ +import XCTest +@testable import NimbleTests + +// This is the entry point for NimbleTests on Linux + +XCTMain([ + testCase(AsyncTest.allTests), + testCase(SynchronousTest.allTests), + testCase(UserDescriptionTest.allTests), + + // Matchers + testCase(AllPassTest.allTests), + testCase(BeAKindOfSwiftTest.allTests), + testCase(BeAnInstanceOfTest.allTests), + testCase(BeCloseToTest.allTests), + testCase(BeginWithTest.allTests), + testCase(BeGreaterThanOrEqualToTest.allTests), + testCase(BeGreaterThanTest.allTests), + testCase(BeIdenticalToObjectTest.allTests), + testCase(BeIdenticalToTest.allTests), + testCase(BeLessThanOrEqualToTest.allTests), + testCase(BeLessThanTest.allTests), + testCase(BeTruthyTest.allTests), + testCase(BeTrueTest.allTests), + testCase(BeFalsyTest.allTests), + testCase(BeFalseTest.allTests), + testCase(BeNilTest.allTests), + testCase(ContainTest.allTests), + testCase(EndWithTest.allTests), + testCase(EqualTest.allTests), + testCase(HaveCountTest.allTests), + testCase(MatchTest.allTests), + // testCase(RaisesExceptionTest.allTests), + testCase(ThrowErrorTest.allTests), + testCase(SatisfyAnyOfTest.allTests), + testCase(PostNotificationTest.allTests), +]) diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..c44b9e6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,257 @@ +import Dispatch +import Foundation +import XCTest +import Nimble + +final class AsyncTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AsyncTest) -> () throws -> Void)] { + return [ + ("testToEventuallyPositiveMatches", testToEventuallyPositiveMatches), + ("testToEventuallyNegativeMatches", testToEventuallyNegativeMatches), + ("testWaitUntilWithCustomDefaultsTimeout", testWaitUntilWithCustomDefaultsTimeout), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ("testSubjectUnderTestIsReleasedFromMemory", testSubjectUnderTestIsReleasedFromMemory), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testToEventuallyPositiveMatches() { + var value = 0 + deferToMainQueue { value = 1 } + expect { value }.toEventually(equal(1)) + + deferToMainQueue { value = 0 } + expect { value }.toEventuallyNot(equal(1)) + } + + func testToEventuallyNegativeMatches() { + let value = 0 + failsWithErrorMessage("expected to eventually not equal <0>, got <0>") { + expect { value }.toEventuallyNot(equal(0)) + } + failsWithErrorMessage("expected to eventually equal <1>, got <0>") { + expect { value }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventually(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventuallyNot(equal(0)) + } + } + + func testToEventuallyWithCustomDefaultTimeout() { + AsyncDefaults.Timeout = 2 + defer { + AsyncDefaults.Timeout = 1 + } + + var value = 0 + + let sleepThenSetValueTo: (Int) -> Void = { newValue in + Thread.sleep(forTimeInterval: 1.1) + value = newValue + } + + var asyncOperation: () -> Void = { sleepThenSetValueTo(1) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventually(equal(1)) + + asyncOperation = { sleepThenSetValueTo(0) } + + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect { value }.toEventuallyNot(equal(1)) + } + + func testWaitUntilWithCustomDefaultsTimeout() { + AsyncDefaults.Timeout = 5 + defer { + AsyncDefaults.Timeout = 1 + } + waitUntil { done in + Thread.sleep(forTimeInterval: 4.8) + done() + } + } + + func testWaitUntilPositiveMatches() { + waitUntil { done in + done() + } + waitUntil { done in + deferToMainQueue { + done() + } + } + } + + func testWaitUntilTimesOutIfNotCalled() { + failsWithErrorMessage("Waited more than 1.0 second") { + waitUntil(timeout: 1) { _ in return } + } + } + + func testWaitUntilTimesOutWhenExceedingItsTime() { + var waiting = true + failsWithErrorMessage("Waited more than 0.01 seconds") { + waitUntil(timeout: 0.01) { done in + let asyncOperation: () -> Void = { + Thread.sleep(forTimeInterval: 0.1) + done() + waiting = false + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + } + } + + // "clear" runloop to ensure this test doesn't poison other tests + repeat { + RunLoop.main.run(until: Date().addingTimeInterval(0.2)) + } while(waiting) + } + + func testWaitUntilNegativeMatches() { + failsWithErrorMessage("expected to equal <2>, got <1>") { + waitUntil { done in + Thread.sleep(forTimeInterval: 0.1) + expect(1).to(equal(2)) + done() + } + } + } + + func testWaitUntilDetectsStalledMainThreadActivity() { + let msg = "-waitUntil() timed out but was unable to run the timeout handler because the main thread is unresponsive (0.5 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." + failsWithErrorMessage(msg) { + waitUntil(timeout: 1) { done in + Thread.sleep(forTimeInterval: 5.0) + done() + } + } + } + + func testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed() { + // Currently we are unable to catch Objective-C exceptions when built by the Swift Package Manager +#if !SWIFT_PACKAGE + let referenceLine = #line + 9 + var msg = "Unexpected exception raised: Nested async expectations are not allowed " + msg += "to avoid creating flaky tests." + msg += "\n\n" + msg += "The call to\n\t" + msg += "expect(...).toEventually(...) at \(#file):\(referenceLine + 7)\n" + msg += "triggered this exception because\n\t" + msg += "waitUntil(...) at \(#file):\(referenceLine + 1)\n" + msg += "is currently managing the main run loop." + failsWithErrorMessage(msg) { // reference line + waitUntil(timeout: 2.0) { done in + var protected: Int = 0 + DispatchQueue.main.async { + protected = 1 + } + + expect(protected).toEventually(equal(1)) + done() + } + } +#endif + } + + func testWaitUntilErrorsIfDoneIsCalledMultipleTimes() { + failsWithErrorMessage("waitUntil(..) expects its completion closure to be only called once") { + waitUntil { done in + deferToMainQueue { + done() + done() + } + } + } + } + + func testWaitUntilMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + waitUntil { done in done() } + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + func testToEventuallyMustBeInMainThread() { +#if !SWIFT_PACKAGE + var executedAsyncBlock: Bool = false + let asyncOperation: () -> Void = { + expect { + expect(1).toEventually(equal(2)) + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + executedAsyncBlock = true + } + if #available(OSX 10.10, *) { + DispatchQueue.global().async(execute: asyncOperation) + } else { + DispatchQueue.global(priority: .default).async(execute: asyncOperation) + } + expect(executedAsyncBlock).toEventually(beTruthy()) +#endif + } + + final class ClassUnderTest { + var deinitCalled: (() -> Void)? + var count = 0 + deinit { deinitCalled?() } + } + + func testSubjectUnderTestIsReleasedFromMemory() { + var subject: ClassUnderTest? = ClassUnderTest() + + if let sub = subject { + expect(sub.count).toEventually(equal(0), timeout: 0.1) + expect(sub.count).toEventuallyNot(equal(1), timeout: 0.1) + } + + waitUntil(timeout: 0.5) { done in + subject?.deinitCalled = { + done() + } + + deferToMainQueue { subject = nil } + } + } + +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift @@ -0,0 +1,7 @@ +import Foundation + +class ObjectWithLazyProperty { + init() {} + lazy var value: String = "hello" + lazy var anotherValue: String = { return "world" }() +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..08a67c6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +extension XCTestCaseProvider { + var allTestNames: [String] { + return type(of: self).allTests.map({ name, _ in + return name + }) + } +} + +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } +} + +extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..a1bbc68 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,100 @@ +import Dispatch +import Foundation +@testable import Nimble +import XCTest + +func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () throws -> Void) { + var filePath = file + var lineNumber = line + + let recorder = AssertionRecorder() + withAssertionHandler(recorder, closure: closure) + + for msg in messages { + var lastFailure: AssertionRecord? + var foundFailureMessage = false + + for assertion in recorder.assertions where assertion.message.stringValue == msg && !assertion.success { + lastFailure = assertion + foundFailureMessage = true + break + } + + if foundFailureMessage { + continue + } + + if preferOriginalSourceLocation { + if let failure = lastFailure { + filePath = failure.location.file + lineNumber = failure.location.line + } + } + + let message: String + if let lastFailure = lastFailure { + message = "Got failure message: \"\(lastFailure.message.stringValue)\", but expected \"\(msg)\"" + } else { + let knownFailures = recorder.assertions.filter { !$0.success }.map { $0.message.stringValue } + let knownFailuresJoined = knownFailures.joined(separator: ", ") + message = "Expected error message (\(msg)), got (\(knownFailuresJoined))\n\nAssertions Received:\n\(recorder.assertions)" + } + NimbleAssertionHandler.assert(false, + message: FailureMessage(stringValue: message), + location: SourceLocation(file: filePath, line: lineNumber)) + } +} + +func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + return failsWithErrorMessage( + [message], + file: file, + line: line, + preferOriginalSourceLocation: preferOriginalSourceLocation, + closure: closure + ) +} + +func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) { + failsWithErrorMessage("\(message) (use beNil() to match nils)", file: file, line: line, preferOriginalSourceLocation: preferOriginalSourceLocation, closure: closure) +} + +func deferToMainQueue(action: @escaping () -> Void) { + DispatchQueue.main.async { + Thread.sleep(forTimeInterval: 0.01) + action() + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +public class NimbleHelper: NSObject { + @objc public class func expectFailureMessage(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessages(_ messages: [NSString], block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessage(messages.map({String(describing: $0)}), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } + + @objc public class func expectFailureMessageForNil(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) { + failsWithErrorMessageForNil(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block) + } +} +#endif + +extension Date { + init(dateTimeString: String) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + let date = dateFormatter.date(from: dateTimeString)! + self.init(timeInterval: 0, since: date) + } +} + +extension NSDate { + convenience init(dateTimeString: String) { + let date = Date(dateTimeString: dateTimeString) + self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift @@ -0,0 +1,9 @@ +import Foundation + +#if os(Linux) + extension NSNotification.Name { + init(_ rawValue: String) { + self.init(rawValue: rawValue) + } + } +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift @@ -0,0 +1,126 @@ +import XCTest +import Nimble + +/// Add operators to `Optional` for conforming `Comparable` that removed in Swift 3.0 +extension Optional where Wrapped: Comparable { + static func < (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } + } + + static func > (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } + } + + static func <= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l <= r + default: + return !(rhs < lhs) + } + } + + static func >= (lhs: Optional, rhs: Optional) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } + } +} + +final class AllPassTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AllPassTest) -> () throws -> Void)] { + return [ + ("testAllPassArray", testAllPassArray), + ("testAllPassMatcher", testAllPassMatcher), + ("testAllPassCollectionsWithOptionalsDontWork", testAllPassCollectionsWithOptionalsDontWork), + ("testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer", testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer), + ("testAllPassSet", testAllPassSet), + ("testAllPassWithNilAsExpectedValue", testAllPassWithNilAsExpectedValue), + ] + } + + func testAllPassArray() { + expect([1, 2, 3, 4]).to(allPass({$0 < 5})) + expect([1, 2, 3, 4]).toNot(allPass({$0 > 5})) + + failsWithErrorMessage( + "expected to all pass a condition, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass({$0 < 3})) + } + failsWithErrorMessage("expected to not all pass a condition") { + expect([1, 2, 3, 4]).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage( + "expected to all be something, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass("be something", {$0 < 3})) + } + failsWithErrorMessage("expected to not all be something") { + expect([1, 2, 3, 4]).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassMatcher() { + expect([1, 2, 3, 4]).to(allPass(beLessThan(5))) + expect([1, 2, 3, 4]).toNot(allPass(beGreaterThan(5))) + + failsWithErrorMessage( + "expected to all be less than <3>, but failed first at element <3> in <[1, 2, 3, 4]>") { + expect([1, 2, 3, 4]).to(allPass(beLessThan(3))) + } + failsWithErrorMessage("expected to not all be less than <5>") { + expect([1, 2, 3, 4]).toNot(allPass(beLessThan(5))) + } + } + + func testAllPassCollectionsWithOptionalsDontWork() { + failsWithErrorMessage("expected to all be nil, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass(beNil())) + } + failsWithErrorMessage("expected to all pass a condition, but failed first at element in <[nil, nil, nil]>") { + expect([nil, nil, nil] as [Int?]).to(allPass({$0 == nil})) + } + } + + func testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer() { + expect([nil, nil, nil] as [Int?]).to(allPass({$0! == nil})) + expect([nil, 1, nil] as [Int?]).toNot(allPass({$0! == nil})) + expect([1, 1, 1] as [Int?]).to(allPass({$0! == 1})) + expect([1, 1, nil] as [Int?]).toNot(allPass({$0! == 1})) + expect([1, 2, 3] as [Int?]).to(allPass({$0! < 4})) + expect([1, 2, 3] as [Int?]).toNot(allPass({$0! < 3})) + expect([1, 2, nil] as [Int?]).to(allPass({$0! < 3})) + } + + func testAllPassSet() { + expect(Set([1, 2, 3, 4])).to(allPass({$0 < 5})) + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 > 5})) + + failsWithErrorMessage("expected to not all pass a condition") { + expect(Set([1, 2, 3, 4])).toNot(allPass({$0 < 5})) + } + failsWithErrorMessage("expected to not all be something") { + expect(Set([1, 2, 3, 4])).toNot(allPass("be something", {$0 < 5})) + } + } + + func testAllPassWithNilAsExpectedValue() { + failsWithErrorMessageForNil("expected to all pass") { + expect(nil as [Int]?).to(allPass(beLessThan(5))) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..bb9041b --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +private class TestNull: NSNull {} +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfSwiftTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + enum TestEnum { + case one, two + } + + func testPositiveMatch() { + expect(1).to(beAKindOf(Int.self)) + expect(1).toNot(beAKindOf(String.self)) + expect("turtle string").to(beAKindOf(String.self)) + expect("turtle string").toNot(beAKindOf(TestClassConformingToProtocol.self)) + + expect(TestEnum.one).to(beAKindOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAKindOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).to(beAKindOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAKindOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAKindOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).to(beAKindOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAKindOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessage("expected to not be a kind of Int, got ") { + expect(1).toNot(beAKindOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to not be a kind of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).toNot(beAKindOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be a kind of String, got ") { + expect(1).to(beAKindOf(String.self)) + } + } +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAKindOfObjCTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testFailureMessages", testFailureMessages), + ] + } + + func testPositiveMatch() { + expect(TestNull()).to(beAKindOf(NSNull.self)) + expect(NSObject()).to(beAKindOf(NSObject.self)) + expect(NSNumber(value: 1)).toNot(beAKindOf(NSDate.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be a kind of NSNull, got ") { + expect(nil as NSNull?).toNot(beAKindOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be a kind of NSString, got ") { + expect(nil as NSString?).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to be a kind of NSString, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).to(beAKindOf(NSString.self)) + } + failsWithErrorMessage("expected to not be a kind of NSNumber, got <__NSCFNumber instance>") { + expect(NSNumber(value: 1)).toNot(beAKindOf(NSNumber.self)) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..aeea28a --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +private protocol TestProtocol {} +private class TestClassConformingToProtocol: TestProtocol {} +private struct TestStructConformingToProtocol: TestProtocol {} + +final class BeAnInstanceOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeAnInstanceOfTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testPositiveMatchSwiftTypes", testPositiveMatchSwiftTypes), + ("testFailureMessages", testFailureMessages), + ("testFailureMessagesSwiftTypes", testFailureMessagesSwiftTypes), + ] + } + + func testPositiveMatch() { + expect(NSNull()).to(beAnInstanceOf(NSNull.self)) + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(NSDate.self)) + } + + enum TestEnum { + case one, two + } + + func testPositiveMatchSwiftTypes() { + expect(1).to(beAnInstanceOf(Int.self)) + expect("test").to(beAnInstanceOf(String.self)) + + expect(TestEnum.one).to(beAnInstanceOf(TestEnum.self)) + + let testProtocolClass = TestClassConformingToProtocol() + expect(testProtocolClass).to(beAnInstanceOf(TestClassConformingToProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolClass).toNot(beAnInstanceOf(TestStructConformingToProtocol.self)) + + let testProtocolStruct = TestStructConformingToProtocol() + expect(testProtocolStruct).to(beAnInstanceOf(TestStructConformingToProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestProtocol.self)) + expect(testProtocolStruct).toNot(beAnInstanceOf(TestClassConformingToProtocol.self)) + } + + func testFailureMessages() { + failsWithErrorMessageForNil("expected to not be an instance of NSNull, got ") { + expect(nil as NSNull?).toNot(beAnInstanceOf(NSNull.self)) + } + failsWithErrorMessageForNil("expected to be an instance of NSString, got ") { + expect(nil as NSString?).to(beAnInstanceOf(NSString.self)) + } +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let numberTypeName = "__NSCFNumber" +#else + let numberTypeName = "NSNumber" +#endif + failsWithErrorMessage("expected to be an instance of NSString, got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).to(beAnInstanceOf(NSString.self)) + } + failsWithErrorMessage("expected to not be an instance of \(numberTypeName), got <\(numberTypeName) instance>") { + expect(NSNumber(value: 1)).toNot(beAnInstanceOf(type(of: NSNumber(value: 1)))) + } + } + + func testFailureMessagesSwiftTypes() { + failsWithErrorMessage("expected to not be an instance of Int, got ") { + expect(1).toNot(beAnInstanceOf(Int.self)) + } + + let testClass = TestClassConformingToProtocol() + failsWithErrorMessage("expected to be an instance of \(String(describing: TestProtocol.self)), got <\(String(describing: TestClassConformingToProtocol.self)) instance>") { + expect(testClass).to(beAnInstanceOf(TestProtocol.self)) + } + + failsWithErrorMessage("expected to be an instance of String, got ") { + expect(1).to(beAnInstanceOf(String.self)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..cb7a3ec --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift @@ -0,0 +1,160 @@ +import Foundation +import XCTest +import Nimble + +final class BeCloseToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeCloseToTest) -> () throws -> Void)] { + return [ + ("testBeCloseTo", testBeCloseTo), + ("testBeCloseToWithin", testBeCloseToWithin), + ("testBeCloseToWithNSNumber", testBeCloseToWithNSNumber), + ("testBeCloseToWithDate", testBeCloseToWithDate), + ("testBeCloseToWithNSDate", testBeCloseToWithNSDate), + ("testBeCloseToOperator", testBeCloseToOperator), + ("testBeCloseToWithinOperator", testBeCloseToWithinOperator), + ("testPlusMinusOperator", testPlusMinusOperator), + ("testBeCloseToOperatorWithDate", testBeCloseToOperatorWithDate), + ("testBeCloseToWithinOperatorWithDate", testBeCloseToWithinOperatorWithDate), + ("testPlusMinusOperatorWithDate", testPlusMinusOperatorWithDate), + ("testBeCloseToArray", testBeCloseToArray), + ("testBeCloseToWithCGFloat", testBeCloseToWithCGFloat), + ] + } + + func testBeCloseTo() { + expect(1.2).to(beCloseTo(1.2001)) + expect(1.2 as CDouble).to(beCloseTo(1.2001)) + expect(1.2 as Float).to(beCloseTo(1.2001)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 0.0001), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001)) + } + } + + func testBeCloseToWithin() { + expect(1.2).to(beCloseTo(9.300, within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(1.2).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithNSNumber() { + expect(NSNumber(value: 1.2)).to(beCloseTo(9.300, within: 10)) + expect(NSNumber(value: 1.2)).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + expect(1.2).to(beCloseTo(NSNumber(value: 9.300), within: 10)) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithCGFloat() { + expect(CGFloat(1.2)).to(beCloseTo(1.2001)) + expect(CGFloat(1.2)).to(beCloseTo(CGFloat(1.2001))) + + failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") { + expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.0)) + } + } + + func testBeCloseToWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(Date(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToWithNSDate() { + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).to(beCloseTo(NSDate(dateTimeString: "2015-08-26 11:43:05"), within: 10)) + + failsWithErrorMessage("expected to not be close to <2015-08-26 11:43:00.0050> (within 0.006), got <2015-08-26 11:43:00.0000>") { + let expectedDate = NSDate(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(NSDate(dateTimeString: "2015-08-26 11:43:00")).toNot(beCloseTo(expectedDate, within: 0.006)) + } + } + + func testBeCloseToOperator() { + expect(1.2) ≈ 1.2001 + expect(1.2 as CDouble) ≈ 1.2001 + + failsWithErrorMessage("expected to be close to <1.2002> (within 0.0001), got <1.2>") { + expect(1.2) ≈ 1.2002 + } + } + + func testBeCloseToWithinOperator() { + expect(1.2) ≈ (9.300, 10) + expect(1.2) == (9.300, 10) + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ (1.0, 0.1) + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == (1.0, 0.1) + } + } + + func testPlusMinusOperator() { + expect(1.2) ≈ 9.300 ± 10 + expect(1.2) == 9.300 ± 10 + + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) ≈ 1.0 ± 0.1 + } + failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") { + expect(1.2) == 1.0 ± 0.1 + } + } + + func testBeCloseToOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:00") + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.0001), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate + } + } + + func testBeCloseToWithinOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (Date(dateTimeString: "2015-08-26 11:43:05"), 10) + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ (expectedDate, 0.004) + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == (expectedDate, 0.004) + } + } + + func testPlusMinusOperatorWithDate() { + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == Date(dateTimeString: "2015-08-26 11:43:05") ± 10 + + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) ≈ expectedDate ± 0.004 + } + failsWithErrorMessage("expected to be close to <2015-08-26 11:43:00.0050> (within 0.004), got <2015-08-26 11:43:00.0000>") { + let expectedDate = Date(dateTimeString: "2015-08-26 11:43:00").addingTimeInterval(0.005) + expect(Date(dateTimeString: "2015-08-26 11:43:00")) == expectedDate ± 0.004 + } + } + + func testBeCloseToArray() { + expect([0.0, 1.1, 2.2]) ≈ [0.0001, 1.1001, 2.2001] + expect([0.0, 1.1, 2.2]).to(beCloseTo([0.1, 1.2, 2.3], within: 0.1)) + + failsWithErrorMessage("expected to be close to <[0, 1]> (each within 0.0001), got <[0, 1.1]>") { + expect([0.0, 1.1]) ≈ [0.0, 1.0] + } + failsWithErrorMessage("expected to be close to <[0.2, 1.2]> (each within 0.1), got <[0, 1.1]>") { + expect([0.0, 1.1]).to(beCloseTo([0.2, 1.2], within: 0.1)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..067ddeb --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift @@ -0,0 +1,82 @@ +import Foundation +import XCTest +import Nimble + +final class BeEmptyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeEmptyTest) -> () throws -> Void)] { + return [ + ("testBeEmptyPositive", testBeEmptyPositive), + ("testBeEmptyNegative", testBeEmptyNegative), + ] + } + + func testBeEmptyPositive() { + expect([] as [Int]).to(beEmpty()) + expect([1]).toNot(beEmpty()) + + expect([] as [CInt]).to(beEmpty()) + expect([1] as [CInt]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary() as? [Int: Int]).to(beEmpty()) + expect(NSDictionary(object: 1, forKey: 1 as NSNumber) as? [Int: Int]).toNot(beEmpty()) +#endif + + expect([Int: Int]()).to(beEmpty()) + expect(["hi": 1]).toNot(beEmpty()) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray() as? [Int]).to(beEmpty()) + expect(NSArray(array: [1]) as? [Int]).toNot(beEmpty()) +#endif + + expect(NSSet()).to(beEmpty()) + expect(NSSet(array: [NSNumber(value: 1)])).toNot(beEmpty()) + + expect(NSIndexSet()).to(beEmpty()) + expect(NSIndexSet(index: 1)).toNot(beEmpty()) + + expect(NSString()).to(beEmpty()) + expect(NSString(string: "hello")).toNot(beEmpty()) + + expect("").to(beEmpty()) + expect("foo").toNot(beEmpty()) + } + + func testBeEmptyNegative() { + failsWithErrorMessageForNil("expected to be empty, got ") { + expect(nil as NSString?).to(beEmpty()) + } + failsWithErrorMessageForNil("expected to not be empty, got ") { + expect(nil as [CInt]?).toNot(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSArray()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <[1]>") { + expect([1]).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <{()}>") { + expect(NSSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <{(1)}>") { + expect(NSSet(object: NSNumber(value: 1))).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <()>") { + expect(NSIndexSet()).toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got <(1)>") { + expect(NSIndexSet(index: 1)).to(beEmpty()) + } + + failsWithErrorMessage("expected to not be empty, got <>") { + expect("").toNot(beEmpty()) + } + failsWithErrorMessage("expected to be empty, got ") { + expect("foo").to(beEmpty()) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..bd73361 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testGreaterThanOrEqualTo", testGreaterThanOrEqualTo), + ("testGreaterThanOrEqualToOperator", testGreaterThanOrEqualToOperator), + ] + } + + func testGreaterThanOrEqualTo() { + expect(10).to(beGreaterThanOrEqualTo(10)) + expect(10).to(beGreaterThanOrEqualTo(2)) + expect(1).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 1)).toNot(beGreaterThanOrEqualTo(2)) + expect(NSNumber(value: 2)).to(beGreaterThanOrEqualTo(NSNumber(value: 2))) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(1).to(beGreaterThanOrEqualTo(NSNumber(value: 0))) +#endif + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <0>") { + expect(0).to(beGreaterThanOrEqualTo(2)) + return + } + failsWithErrorMessage("expected to not be greater than or equal to <1>, got <1>") { + expect(1).toNot(beGreaterThanOrEqualTo(1)) + return + } + failsWithErrorMessageForNil("expected to be greater than or equal to <-2>, got ") { + expect(nil as Int?).to(beGreaterThanOrEqualTo(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than or equal to <1>, got ") { + expect(nil as Int?).toNot(beGreaterThanOrEqualTo(1)) + } + } + + func testGreaterThanOrEqualToOperator() { + expect(0) >= 0 + expect(1) >= 0 + expect(NSNumber(value: 1)) >= 1 + expect(NSNumber(value: 1)) >= NSNumber(value: 1) + expect(2.5) >= 2.5 + expect(2.5) >= 2 + expect(Float(2.5)) >= Float(2.5) + expect(Float(2.5)) >= 2 + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <1>") { + expect(1) >= 2 + return + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..9c33e4b --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeGreaterThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeGreaterThanTest) -> () throws -> Void)] { + return [ + ("testGreaterThan", testGreaterThan), + ("testGreaterThanOperator", testGreaterThanOperator), + ] + } + + func testGreaterThan() { + expect(10).to(beGreaterThan(2)) + expect(1).toNot(beGreaterThan(2)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 3)).to(beGreaterThan(2)) +#else + expect(NSNumber(value: 3)).to(beGreaterThan(2 as NSNumber)) +#endif + expect(NSNumber(value: 1)).toNot(beGreaterThan(NSNumber(value: 2))) + + failsWithErrorMessage("expected to be greater than <2>, got <0>") { + expect(0).to(beGreaterThan(2)) + } + failsWithErrorMessage("expected to not be greater than <0>, got <1>") { + expect(1).toNot(beGreaterThan(0)) + } + failsWithErrorMessageForNil("expected to be greater than <-2>, got ") { + expect(nil as Int?).to(beGreaterThan(-2)) + } + failsWithErrorMessageForNil("expected to not be greater than <0>, got ") { + expect(nil as Int?).toNot(beGreaterThan(0)) + } + } + + func testGreaterThanOperator() { + expect(1) > 0 + expect(NSNumber(value: 1)) > NSNumber(value: 0) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 1)) > 0 +#else + expect(NSNumber(value: 1)) > 0 as NSNumber +#endif + expect(2.5) > 1.5 + expect(Float(2.5)) > Float(1.5) + + failsWithErrorMessage("expected to be greater than <2>, got <1>") { + expect(1) > 2 + return + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift @@ -0,0 +1,64 @@ +import Foundation +import XCTest +import Nimble + +final class BeIdenticalToObjectTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToObjectTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testFailsOnNils", testFailsOnNils), + ("testOperators", testOperators), + ] + } + + private class BeIdenticalToObjectTester {} + private let testObjectA = BeIdenticalToObjectTester() + private let testObjectB = BeIdenticalToObjectTester() + + func testBeIdenticalToPositive() { + expect(self.testObjectA).to(beIdenticalTo(testObjectA)) + } + + func testBeIdenticalToNegative() { + expect(self.testObjectA).toNot(beIdenticalTo(testObjectB)) + } + + func testBeIdenticalToPositiveMessage() { + let message = String(describing: NSString(format: "expected to be identical to <%p>, got <%p>", + unsafeBitCast(testObjectB, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).to(beIdenticalTo(self.testObjectB)) + } + } + + func testBeIdenticalToNegativeMessage() { + let message = String(describing: NSString(format: "expected to not be identical to <%p>, got <%p>", + unsafeBitCast(testObjectA, to: Int.self), unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessage(message) { + expect(self.testObjectA).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testFailsOnNils() { + let message1 = String(describing: NSString(format: "expected to be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message1) { + expect(nil as BeIdenticalToObjectTester?).to(beIdenticalTo(self.testObjectA)) + } + + let message2 = String(describing: NSString(format: "expected to not be identical to <%p>, got nil", + unsafeBitCast(testObjectA, to: Int.self))) + failsWithErrorMessageForNil(message2) { + expect(nil as BeIdenticalToObjectTester?).toNot(beIdenticalTo(self.testObjectA)) + } + } + + func testOperators() { + expect(self.testObjectA) === testObjectA + expect(self.testObjectA) !== testObjectB + } + +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..6b629b0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift @@ -0,0 +1,68 @@ +import Foundation +import XCTest +@testable import Nimble + +final class BeIdenticalToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeIdenticalToTest) -> () throws -> Void)] { + return [ + ("testBeIdenticalToPositive", testBeIdenticalToPositive), + ("testBeIdenticalToNegative", testBeIdenticalToNegative), + ("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage), + ("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage), + ("testOperators", testOperators), + ("testBeAlias", testBeAlias), + ] + } + + func testBeIdenticalToPositive() { + let value = NSDate() + expect(value).to(beIdenticalTo(value)) + } + + func testBeIdenticalToNegative() { + expect(NSNumber(value: 1)).toNot(beIdenticalTo(NSString(string: "yo"))) + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + } + + func testBeIdenticalToPositiveMessage() { + let num1 = NSNumber(value: 1) + let num2 = NSNumber(value: 2) + let message = "expected to be identical to \(identityAsString(num2)), got \(identityAsString(num1))" + failsWithErrorMessage(message) { + expect(num1).to(beIdenticalTo(num2)) + } + } + + func testBeIdenticalToNegativeMessage() { + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value2)), got \(identityAsString(value1))" + failsWithErrorMessage(message) { + expect(value1).toNot(beIdenticalTo(value2)) + } + } + + func testOperators() { + let value = NSDate() + expect(value) === value + expect(NSNumber(value: 1)) !== NSNumber(value: 2) + } + + func testBeAlias() { + let value = NSDate() + expect(value).to(be(value)) + expect(NSNumber(value: 1)).toNot(be(NSString(string: "turtles"))) + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect([1]).toNot(be([1])) + #else + expect(NSArray(array: [NSNumber(value: 1)])).toNot(beIdenticalTo(NSArray(array: [NSNumber(value: 1)]))) + #endif + + let value1 = NSArray(array: []) + let value2 = value1 + let message = "expected to not be identical to \(identityAsString(value1)), got \(identityAsString(value2))" + failsWithErrorMessage(message) { + expect(value1).toNot(be(value2)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..428ace4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanOrEqualToTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanOrEqualToTest) -> () throws -> Void)] { + return [ + ("testLessThanOrEqualTo", testLessThanOrEqualTo), + ("testLessThanOrEqualToOperator", testLessThanOrEqualToOperator), + ] + } + + func testLessThanOrEqualTo() { + expect(10).to(beLessThanOrEqualTo(10)) + expect(2).to(beLessThanOrEqualTo(10)) + expect(2).toNot(beLessThanOrEqualTo(1)) + + expect(NSNumber(value: 2)).to(beLessThanOrEqualTo(10)) + expect(NSNumber(value: 2)).toNot(beLessThanOrEqualTo(1)) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(2).to(beLessThanOrEqualTo(NSNumber(value: 10))) + expect(2).toNot(beLessThanOrEqualTo(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than or equal to <0>, got <2>") { + expect(2).to(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessage("expected to not be less than or equal to <0>, got <0>") { + expect(0).toNot(beLessThanOrEqualTo(0)) + return + } + failsWithErrorMessageForNil("expected to be less than or equal to <2>, got ") { + expect(nil as Int?).to(beLessThanOrEqualTo(2)) + return + } + failsWithErrorMessageForNil("expected to not be less than or equal to <-2>, got ") { + expect(nil as Int?).toNot(beLessThanOrEqualTo(-2)) + return + } + } + + func testLessThanOrEqualToOperator() { + expect(0) <= 1 + expect(1) <= 1 + + failsWithErrorMessage("expected to be less than or equal to <1>, got <2>") { + expect(2) <= 1 + return + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..90ba1b9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift @@ -0,0 +1,57 @@ +import Foundation +import XCTest +import Nimble + +final class BeLessThanTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeLessThanTest) -> () throws -> Void)] { + return [ + ("testLessThan", testLessThan), + ("testLessThanOperator", testLessThanOperator), + ] + } + + func testLessThan() { + expect(2).to(beLessThan(10)) + expect(2).toNot(beLessThan(1)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 2)).to(beLessThan(10)) + expect(NSNumber(value: 2)).toNot(beLessThan(1)) + + expect(2).to(beLessThan(NSNumber(value: 10))) + expect(2).toNot(beLessThan(NSNumber(value: 1))) +#else + expect(NSNumber(value: 2)).to(beLessThan(10 as NSNumber)) + expect(NSNumber(value: 2)).toNot(beLessThan(1 as NSNumber)) + + expect(2 as NSNumber).to(beLessThan(NSNumber(value: 10))) + expect(2 as NSNumber).toNot(beLessThan(NSNumber(value: 1))) +#endif + + failsWithErrorMessage("expected to be less than <0>, got <2>") { + expect(2).to(beLessThan(0)) + } + failsWithErrorMessage("expected to not be less than <1>, got <0>") { + expect(0).toNot(beLessThan(1)) + } + + failsWithErrorMessageForNil("expected to be less than <2>, got ") { + expect(nil as Int?).to(beLessThan(2)) + } + failsWithErrorMessageForNil("expected to not be less than <-1>, got ") { + expect(nil as Int?).toNot(beLessThan(-1)) + } + } + + func testLessThanOperator() { + expect(0) < 1 +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(NSNumber(value: 0)) < 1 +#else + expect(NSNumber(value: 0)) < 1 as NSNumber +#endif + failsWithErrorMessage("expected to be less than <1>, got <2>") { + expect(2) < 1 + return + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift @@ -0,0 +1,270 @@ +import XCTest +import Nimble +import Foundation + +enum ConvertsToBool: ExpressibleByBooleanLiteral, CustomStringConvertible { + case trueLike, falseLike + + typealias BooleanLiteralType = Bool + + init(booleanLiteral value: Bool) { + switch value { + case true: self = .trueLike + case false: self = .falseLike + } + } + + var boolValue: Bool { + switch self { + case .trueLike: return true + case .falseLike: return false + } + } + + var description: String { + switch self { + case .trueLike: return "TrueLike" + case .falseLike: return "FalseLike" + } + } +} + +final class BeTruthyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTruthyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNonNilTypes", testShouldMatchNonNilTypes), + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchNilTypes", testShouldNotMatchNilTypes), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ("testShouldMatchBoolConvertibleTypesThatConvertToTrue", testShouldMatchBoolConvertibleTypesThatConvertToTrue), + ("testShouldNotMatchBoolConvertibleTypesThatConvertToFalse", testShouldNotMatchBoolConvertibleTypesThatConvertToFalse), + ] + } + + func testShouldMatchNonNilTypes() { + expect(true as Bool?).to(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).to(beTruthy()) + expect(1 as UInt8?).to(beTruthy()) + expect(1 as Int16?).to(beTruthy()) + expect(1 as UInt16?).to(beTruthy()) + expect(1 as Int32?).to(beTruthy()) + expect(1 as UInt32?).to(beTruthy()) + expect(1 as Int64?).to(beTruthy()) + expect(1 as UInt64?).to(beTruthy()) + expect(1 as Float?).to(beTruthy()) + expect(1 as Double?).to(beTruthy()) + expect(1 as Int?).to(beTruthy()) + expect(1 as UInt?).to(beTruthy()) + } + + func testShouldMatchTrue() { + expect(true).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(true).toNot(beTruthy()) + } + } + + func testShouldNotMatchNilTypes() { + expect(false as Bool?).toNot(beTruthy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).toNot(beTruthy()) + expect(nil as Int8?).toNot(beTruthy()) + expect(nil as UInt8?).toNot(beTruthy()) + expect(nil as Int16?).toNot(beTruthy()) + expect(nil as UInt16?).toNot(beTruthy()) + expect(nil as Int32?).toNot(beTruthy()) + expect(nil as UInt32?).toNot(beTruthy()) + expect(nil as Int64?).toNot(beTruthy()) + expect(nil as UInt64?).toNot(beTruthy()) + expect(nil as Float?).toNot(beTruthy()) + expect(nil as Double?).toNot(beTruthy()) + expect(nil as Int?).toNot(beTruthy()) + expect(nil as UInt?).toNot(beTruthy()) + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(false).to(beTruthy()) + } + } + + func testShouldNotMatchNilBools() { + expect(nil as Bool?).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(nil as Bool?).to(beTruthy()) + } + } + + func testShouldMatchBoolConvertibleTypesThatConvertToTrue() { + expect(ConvertsToBool.trueLike).to(beTruthy()) + + failsWithErrorMessage("expected to not be truthy, got ") { + expect(ConvertsToBool.trueLike).toNot(beTruthy()) + } + } + + func testShouldNotMatchBoolConvertibleTypesThatConvertToFalse() { + expect(ConvertsToBool.falseLike).toNot(beTruthy()) + + failsWithErrorMessage("expected to be truthy, got ") { + expect(ConvertsToBool.falseLike).to(beTruthy()) + } + } +} + +final class BeTrueTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeTrueTest) -> () throws -> Void)] { + return [ + ("testShouldMatchTrue", testShouldMatchTrue), + ("testShouldNotMatchFalse", testShouldNotMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldMatchTrue() { + expect(true).to(beTrue()) + + failsWithErrorMessage("expected to not be true, got ") { + expect(true).toNot(beTrue()) + } + } + + func testShouldNotMatchFalse() { + expect(false).toNot(beTrue()) + + failsWithErrorMessage("expected to be true, got ") { + expect(false).to(beTrue()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to not be true, got ") { + expect(nil as Bool?).toNot(beTrue()) + } + + failsWithErrorMessageForNil("expected to be true, got ") { + expect(nil as Bool?).to(beTrue()) + } + } +} + +final class BeFalsyTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalsyTest) -> () throws -> Void)] { + return [ + ("testShouldMatchNilTypes", testShouldMatchNilTypes), + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldNotMatchNonNilTypes", testShouldNotMatchNonNilTypes), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldMatchNilBools", testShouldMatchNilBools), + ] + } + + func testShouldMatchNilTypes() { + expect(false as Bool?).to(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(nil as Bool?).to(beFalsy()) + expect(nil as Int8?).to(beFalsy()) + expect(nil as UInt8?).to(beFalsy()) + expect(nil as Int16?).to(beFalsy()) + expect(nil as UInt16?).to(beFalsy()) + expect(nil as Int32?).to(beFalsy()) + expect(nil as UInt32?).to(beFalsy()) + expect(nil as Int64?).to(beFalsy()) + expect(nil as UInt64?).to(beFalsy()) + expect(nil as Float?).to(beFalsy()) + expect(nil as Double?).to(beFalsy()) + expect(nil as Int?).to(beFalsy()) + expect(nil as UInt?).to(beFalsy()) + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalsy()) + + failsWithErrorMessage("expected to be falsy, got ") { + expect(true).to(beFalsy()) + } + } + + func testShouldNotMatchNonNilTypes() { + expect(true as Bool?).toNot(beFalsy()) + + // Support types conforming to `ExpressibleByBooleanLiteral` + // Nimble extend following types as conforming to `ExpressibleByBooleanLiteral` + expect(1 as Int8?).toNot(beFalsy()) + expect(1 as UInt8?).toNot(beFalsy()) + expect(1 as Int16?).toNot(beFalsy()) + expect(1 as UInt16?).toNot(beFalsy()) + expect(1 as Int32?).toNot(beFalsy()) + expect(1 as UInt32?).toNot(beFalsy()) + expect(1 as Int64?).toNot(beFalsy()) + expect(1 as UInt64?).toNot(beFalsy()) + expect(1 as Float?).toNot(beFalsy()) + expect(1 as Double?).toNot(beFalsy()) + expect(1 as Int?).toNot(beFalsy()) + expect(1 as UInt?).toNot(beFalsy()) + } + + func testShouldMatchFalse() { + expect(false).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(false).toNot(beFalsy()) + } + } + + func testShouldMatchNilBools() { + expect(nil as Bool?).to(beFalsy()) + + failsWithErrorMessage("expected to not be falsy, got ") { + expect(nil as Bool?).toNot(beFalsy()) + } + } +} + +final class BeFalseTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeFalseTest) -> () throws -> Void)] { + return [ + ("testShouldNotMatchTrue", testShouldNotMatchTrue), + ("testShouldMatchFalse", testShouldMatchFalse), + ("testShouldNotMatchNilBools", testShouldNotMatchNilBools), + ] + } + + func testShouldNotMatchTrue() { + expect(true).toNot(beFalse()) + + failsWithErrorMessage("expected to be false, got ") { + expect(true).to(beFalse()) + } + } + + func testShouldMatchFalse() { + expect(false).to(beFalse()) + + failsWithErrorMessage("expected to not be false, got ") { + expect(false).toNot(beFalse()) + } + } + + func testShouldNotMatchNilBools() { + failsWithErrorMessageForNil("expected to be false, got ") { + expect(nil as Bool?).to(beFalse()) + } + + failsWithErrorMessageForNil("expected to not be false, got ") { + expect(nil as Bool?).toNot(beFalse()) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift @@ -0,0 +1,28 @@ +import XCTest +import Nimble + +final class BeNilTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeNilTest) -> () throws -> Void)] { + return [ + ("testBeNil", testBeNil), + ] + } + + func producesNil() -> [Int]? { + return nil + } + + func testBeNil() { + expect(nil as Int?).to(beNil()) + expect(1 as Int?).toNot(beNil()) + expect(self.producesNil()).to(beNil()) + + failsWithErrorMessage("expected to not be nil, got ") { + expect(nil as Int?).toNot(beNil()) + } + + failsWithErrorMessage("expected to be nil, got <1>") { + expect(1 as Int?).to(beNil()) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift @@ -0,0 +1,32 @@ +import XCTest +import Nimble + +final class BeVoidTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeVoidTest) -> () throws -> Void)] { + return [ + ("testBeVoid", testBeVoid), + ] + } + + func testBeVoid() { + expect(()).to(beVoid()) + expect(() as ()?).to(beVoid()) + expect(nil as ()?).toNot(beVoid()) + + expect(()) == () + expect(() as ()?) == () + expect(nil as ()?) != () + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(()).toNot(beVoid()) + } + + failsWithErrorMessage("expected to not be void, got <()>") { + expect(() as ()?).toNot(beVoid()) + } + + failsWithErrorMessage("expected to be void, got ") { + expect(nil as ()?).to(beVoid()) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..276c7d0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift @@ -0,0 +1,53 @@ +import Foundation +import XCTest +import Nimble + +final class BeginWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeginWithTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testNegativeMatches", testNegativeMatches), + ] + } + + func testPositiveMatches() { + expect([1, 2, 3]).to(beginWith(1)) + expect([1, 2, 3]).toNot(beginWith(2)) + + expect("foobar").to(beginWith("foo")) + expect("foobar").toNot(beginWith("oo")) + + expect("foobarfoo").to(beginWith("foo")) + + expect(NSString(string: "foobar").description).to(beginWith("foo")) + expect(NSString(string: "foobar").description).toNot(beginWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(beginWith("a")) + expect(NSArray(array: ["a", "b"])).toNot(beginWith("b")) +#endif + } + + func testNegativeMatches() { + failsWithErrorMessageForNil("expected to begin with , got ") { + expect(nil as NSArray?).to(beginWith(NSString(string: "b"))) + } + failsWithErrorMessageForNil("expected to not begin with , got ") { + expect(nil as NSArray?).toNot(beginWith(NSString(string: "b"))) + } + + failsWithErrorMessage("expected to begin with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(beginWith(2)) + } + failsWithErrorMessage("expected to not begin with <1>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(beginWith(1)) + } + failsWithErrorMessage("expected to begin with , got ") { + expect("batman").to(beginWith("atm")) + } + failsWithErrorMessage("expected to not begin with , got ") { + expect("batman").toNot(beginWith("bat")) + } + } + +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift @@ -0,0 +1,86 @@ +import Foundation +import XCTest +import Nimble + +final class ContainElementSatisfyingTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainElementSatisfyingTest) -> () throws -> Void)] { + return [ + ("testContainElementSatisfying", testContainElementSatisfying), + ("testContainElementSatisfyingDefaultErrorMessage", testContainElementSatisfyingDefaultErrorMessage), + ("testContainElementSatisfyingSpecificErrorMessage", testContainElementSatisfyingSpecificErrorMessage), + ("testContainElementSatisfyingNegativeCase", + testContainElementSatisfyingNegativeCase), + ("testContainElementSatisfyingNegativeCaseDefaultErrorMessage", + testContainElementSatisfyingNegativeCaseDefaultErrorMessage), + ("testContainElementSatisfyingNegativeCaseSpecificErrorMessage", + testContainElementSatisfyingNegativeCaseSpecificErrorMessage), + ] + } + + func testContainElementSatisfying() { + var orderIndifferentArray = [1, 2, 3] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + + orderIndifferentArray = [3, 1, 2] + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 1 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 2 + })) + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 3 + })) + } + + func testContainElementSatisfyingDefaultErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + })) + } + } + + func testContainElementSatisfyingSpecificErrorMessage() { + let orderIndifferentArray = [1, 2, 3] + failsWithErrorMessage("expected to find object in collection equal to 4") { + expect(orderIndifferentArray).to(containElementSatisfying({ number in + return number == 4 + }, "equal to 4")) + } + } + + func testContainElementSatisfyingNegativeCase() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "armadillos" + })) + } + + func testContainElementSatisfyingNegativeCaseDefaultErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + })) + } + } + + func testContainElementSatisfyingNegativeCaseSpecificErrorMessage() { + let orderIndifferentArray = ["puppies", "kittens", "turtles"] + failsWithErrorMessage("expected to not find object in collection equal to 'kittens'") { + expect(orderIndifferentArray).toNot(containElementSatisfying({ string in + return string == "kittens" + }, "equal to 'kittens'")) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..1d8a1eb --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift @@ -0,0 +1,95 @@ +import Foundation +import XCTest +import Nimble + +final class ContainTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ContainTest) -> () throws -> Void)] { + return [ + ("testContain", testContain), + ("testContainSubstring", testContainSubstring), + ("testContainObjCSubstring", testContainObjCSubstring), + ("testVariadicArguments", testVariadicArguments), + ("testCollectionArguments", testCollectionArguments), + ] + } + + func testContain() { + expect([1, 2, 3]).to(contain(1)) + expect([1, 2, 3] as [CInt]).to(contain(1 as CInt)) + expect([1, 2, 3] as [CInt]).toNot(contain(4 as CInt)) + expect(["foo", "bar", "baz"]).to(contain("baz")) + expect([1, 2, 3]).toNot(contain(4)) + expect(["foo", "bar", "baz"]).toNot(contain("ba")) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a"])).to(contain(NSString(string: "a"))) + expect(NSArray(array: ["a"])).toNot(contain(NSString(string: "b"))) + expect(NSArray(object: 1) as NSArray?).to(contain(1)) +#endif + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b")) + } + + failsWithErrorMessageForNil("expected to contain , got ") { + expect(nil as [String]?).to(contain("bar")) + } + failsWithErrorMessageForNil("expected to not contain , got ") { + expect(nil as [String]?).toNot(contain("b")) + } + } + + func testContainSubstring() { + expect("foo").to(contain("o")) + expect("foo").to(contain("oo")) + expect("foo").toNot(contain("z")) + expect("foo").toNot(contain("zz")) + + failsWithErrorMessage("expected to contain , got ") { + expect("foo").to(contain("bar")) + } + failsWithErrorMessage("expected to not contain , got ") { + expect("foo").toNot(contain("oo")) + } + } + + func testContainObjCSubstring() { + let str = NSString(string: "foo") + expect(str).to(contain(NSString(string: "o"))) + expect(str).to(contain(NSString(string: "oo"))) + expect(str).toNot(contain(NSString(string: "z"))) + expect(str).toNot(contain(NSString(string: "zz"))) + } + + func testVariadicArguments() { + expect([1, 2, 3]).to(contain(1, 2)) + expect([1, 2, 3]).toNot(contain(1, 4)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain("a", "bar")) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain("b", "a")) + } + } + + func testCollectionArguments() { + expect([1, 2, 3]).to(contain([1, 2])) + expect([1, 2, 3]).toNot(contain([1, 4])) + + let collection = Array(1...10) + let slice = Array(collection[3...5]) + expect(collection).to(contain(slice)) + + failsWithErrorMessage("expected to contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).to(contain(["a", "bar"])) + } + + failsWithErrorMessage("expected to not contain , got <[a, b, c]>") { + expect(["a", "b", "c"]).toNot(contain(["b", "a"])) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..30e3b26 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift @@ -0,0 +1,56 @@ +import Foundation +import XCTest +import Nimble + +final class EndWithTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EndWithTest) -> () throws -> Void)] { + return [ + ("testEndWithPositives", testEndWithPositives), + ("testEndWithNegatives", testEndWithNegatives), + ] + } + + func testEndWithPositives() { + expect([1, 2, 3]).to(endWith(3)) + expect([1, 2, 3]).toNot(endWith(2)) + expect([]).toNot(endWith(1)) + expect(["a", "b", "a"]).to(endWith("a")) + + expect("foobar").to(endWith("bar")) + expect("foobar").toNot(endWith("oo")) + expect("foobarfoo").to(endWith("foo")) + + expect(NSString(string: "foobar").description).to(endWith("bar")) + expect(NSString(string: "foobar").description).toNot(endWith("oo")) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: ["a", "b"])).to(endWith("b")) + expect(NSArray(array: ["a", "b"])).toNot(endWith("a")) + expect(NSArray(array: [])).toNot(endWith("a")) + expect(NSArray(array: ["a", "b", "a"])).to(endWith("a")) +#endif + } + + func testEndWithNegatives() { + failsWithErrorMessageForNil("expected to end with <2>, got ") { + expect(nil as [Int]?).to(endWith(2)) + } + failsWithErrorMessageForNil("expected to not end with <2>, got ") { + expect(nil as [Int]?).toNot(endWith(2)) + } + + failsWithErrorMessage("expected to end with <2>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(endWith(2)) + } + failsWithErrorMessage("expected to not end with <3>, got <[1, 2, 3]>") { + expect([1, 2, 3]).toNot(endWith(3)) + } + failsWithErrorMessage("expected to end with , got ") { + expect("batman").to(endWith("atm")) + } + failsWithErrorMessage("expected to not end with , got ") { + expect("batman").toNot(endWith("man")) + } + } + +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..85be751 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift @@ -0,0 +1,276 @@ +import Foundation +import XCTest +import Nimble + +final class EqualTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (EqualTest) -> () throws -> Void)] { + return [ + ("testEquality", testEquality), + ("testArrayEquality", testArrayEquality), + ("testSetEquality", testSetEquality), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ("testDictionaryEquality", testDictionaryEquality), + ("testDataEquality", testDataEquality), + ("testNSObjectEquality", testNSObjectEquality), + ("testOperatorEquality", testOperatorEquality), + ("testOperatorEqualityWithArrays", testOperatorEqualityWithArrays), + ("testOperatorEqualityWithDictionaries", testOperatorEqualityWithDictionaries), + ("testOptionalEquality", testOptionalEquality), + ("testArrayOfOptionalsEquality", testArrayOfOptionalsEquality), + ("testDictionariesWithDifferentSequences", testDictionariesWithDifferentSequences), + ] + } + + func testEquality() { + expect(1 as CInt).to(equal(1 as CInt)) + expect(1 as CInt).to(equal(1)) + expect(1).to(equal(1)) + expect("hello").to(equal("hello")) + expect("hello").toNot(equal("world")) + + expect { + 1 + }.to(equal(1)) + + failsWithErrorMessage("expected to equal , got ") { + expect("hello").to(equal("world")) + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello").toNot(equal("hello")) + } + } + + func testArrayEquality() { + expect([1, 2, 3]).to(equal([1, 2, 3])) + expect([1, 2, 3]).toNot(equal([1, 2])) + expect([1, 2, 3]).toNot(equal([1, 2, 4])) + + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + expect(array1).to(equal(array2)) + expect(array1).to(equal([1, 2, 3])) + expect(array1).toNot(equal([1, 2] as [Int])) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSArray(array: [1, 2, 3])).to(equal(NSArray(array: [1, 2, 3]))) +#endif + + failsWithErrorMessage("expected to equal <[1, 2]>, got <[1, 2, 3]>") { + expect([1, 2, 3]).to(equal([1, 2])) + } + } + + func testSetEquality() { + expect(Set([1, 2])).to(equal(Set([1, 2]))) + expect(Set()).to(equal(Set())) + expect(Set()) == Set() + expect(Set([1, 2])) != Set() + + failsWithErrorMessageForNil("expected to equal <[1, 2]>, got ") { + expect(nil as Set?).to(equal(Set([1, 2]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3]>, missing <[1]>") { + expect(Set([2, 3])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[1, 2, 3, 4]>, extra <[4]>") { + expect(Set([1, 2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])).to(equal(Set([1, 2, 3]))) + } + + failsWithErrorMessage("expected to equal <[1, 2, 3]>, got <[2, 3, 4]>, missing <[1]>, extra <[4]>") { + expect(Set([2, 3, 4])) == Set([1, 2, 3]) + } + + failsWithErrorMessage("expected to not equal <[1, 2, 3]>, got <[1, 2, 3]>") { + expect(Set([1, 2, 3])) != Set([1, 2, 3]) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as String?).to(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect("foo").toNot(equal(nil as String?)) + } + failsWithErrorMessageForNil("expected to not equal , got ") { + expect(nil as String?).toNot(equal("bar")) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int]?).to(equal(nil as [Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1]>, got ") { + expect(nil as [Int]?).toNot(equal([1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1]>") { + expect([1]).toNot(equal(nil as [Int]?)) + } + + failsWithErrorMessageForNil("expected to equal , got ") { + expect(nil as [Int: Int]?).to(equal(nil as [Int: Int]?)) + } + failsWithErrorMessageForNil("expected to not equal <[1: 1]>, got ") { + expect(nil as [Int: Int]?).toNot(equal([1: 1])) + } + failsWithErrorMessageForNil("expected to not equal , got <[1: 1]>") { + expect([1: 1]).toNot(equal(nil as [Int: Int]?)) + } + + failsWithErrorMessageForNil("expected to not equal , got <1>") { + expect(1).toNot(equal(nil)) + } + } + + func testDictionaryEquality() { + expect(["foo": "bar"]).to(equal(["foo": "bar"])) + expect(["foo": "bar"]).toNot(equal(["foo": "baz"])) + + let actual = ["foo": "bar"] + let expected = ["foo": "bar"] + let unexpected = ["foo": "baz"] + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString)).to(equal(["foo": "bar"])) + expect(NSDictionary(object: "bar", forKey: "foo" as NSString) as? [String: String]).to(equal(expected)) +#endif + } + + func testDataEquality() { + let actual = "foobar".data(using: .utf8) + let expected = "foobar".data(using: .utf8) + let unexpected = "foobarfoo".data(using: .utf8) + + expect(actual).to(equal(expected)) + expect(actual).toNot(equal(unexpected)) + + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11) + let expectedErrorMessage = "expected to equal >, got >" + #else + let expectedErrorMessage = "expected to equal >," + + " got >" + #endif + + failsWithErrorMessage(expectedErrorMessage) { + expect(actual).to(equal(unexpected)) + } + } + + func testNSObjectEquality() { + expect(NSNumber(value: 1)).to(equal(NSNumber(value: 1))) + expect(NSNumber(value: 1)) == NSNumber(value: 1) + expect(NSNumber(value: 1)) != NSNumber(value: 2) + expect { NSNumber(value: 1) }.to(equal(1)) + } + + func testOperatorEquality() { + expect("foo") == "foo" + expect("foo") != "bar" + + failsWithErrorMessage("expected to equal , got ") { + expect("hello") == "world" + return + } + failsWithErrorMessage("expected to not equal , got ") { + expect("hello") != "hello" + return + } + } + + func testOperatorEqualityWithArrays() { + let array1: [Int] = [1, 2, 3] + let array2: [Int] = [1, 2, 3] + let array3: [Int] = [1, 2] + expect(array1) == array2 + expect(array1) != array3 + } + + func testOperatorEqualityWithDictionaries() { + let dict1 = ["foo": "bar"] + let dict2 = ["foo": "bar"] + let dict3 = ["foo": "baz"] + expect(dict1) == dict2 + expect(dict1) != dict3 + } + + func testOptionalEquality() { + expect(1 as CInt?).to(equal(1)) + expect(1 as CInt?).to(equal(1 as CInt?)) + } + + func testArrayOfOptionalsEquality() { + let array1: [Int?] = [1, nil, 3] + let array2: [Int?] = [nil, 2, 3] + let array3: [Int?] = [1, nil, 3] + + expect(array1).toNot(equal(array2)) + expect(array1).to(equal(array3)) + expect(array2).toNot(equal(array3)) + + let allNils1: [String?] = [nil, nil, nil, nil] + let allNils2: [String?] = [nil, nil, nil, nil] + let notReallyAllNils: [String?] = [nil, nil, nil, "turtles"] + + expect(allNils1).to(equal(allNils2)) + expect(allNils1).toNot(equal(notReallyAllNils)) + + let noNils1: [Int?] = [1, 2, 3, 4, 5] + let noNils2: [Int?] = [1, 3, 5, 7, 9] + + expect(noNils1).toNot(equal(noNils2)) + + failsWithErrorMessage("expected to equal <[Optional(1), nil]>, got <[nil, Optional(2)]>") { + let arrayOfOptionalInts: [Int?] = [nil, 2] + let anotherArrayOfOptionalInts: [Int?] = [1, nil] + expect(arrayOfOptionalInts).to(equal(anotherArrayOfOptionalInts)) + return + } + } + + func testDictionariesWithDifferentSequences() { + // see: https://github.com/Quick/Nimble/issues/61 + // these dictionaries generate different orderings of sequences. + let result = ["how": 1, "think": 1, "didnt": 2, "because": 1, + "interesting": 1, "always": 1, "right": 1, "such": 1, + "to": 3, "say": 1, "cool": 1, "you": 1, + "weather": 3, "be": 1, "went": 1, "was": 2, + "sometimes": 1, "and": 3, "mind": 1, "rain": 1, + "whole": 1, "everything": 1, "weather.": 1, "down": 1, + "kind": 1, "mood.": 1, "it": 2, "everyday": 1, "might": 1, + "more": 1, "have": 2, "person": 1, "could": 1, "tenth": 2, + "night": 1, "write": 1, "Youd": 1, "affects": 1, "of": 3, + "Who": 1, "us": 1, "an": 1, "I": 4, "my": 1, "much": 2, + "wrong.": 1, "peacefully.": 1, "amazing": 3, "would": 4, + "just": 1, "grade.": 1, "Its": 2, "The": 2, "had": 1, "that": 1, + "the": 5, "best": 1, "but": 1, "essay": 1, "for": 1, "summer": 2, + "your": 1, "grade": 1, "vary": 1, "pretty": 1, "at": 1, "rain.": 1, + "about": 1, "allow": 1, "thought": 1, "in": 1, "sleep": 1, "a": 1, + "hot": 1, "really": 1, "beach": 1, "life.": 1, "we": 1, "although": 1, ] + + let storyCount = ["The": 2, "summer": 2, "of": 3, "tenth": 2, "grade": 1, + "was": 2, "the": 5, "best": 1, "my": 1, "life.": 1, "I": 4, + "went": 1, "to": 3, "beach": 1, "everyday": 1, "and": 3, + "we": 1, "had": 1, "amazing": 3, "weather.": 1, "weather": 3, + "didnt": 2, "really": 1, "vary": 1, "much": 2, "always": 1, + "pretty": 1, "hot": 1, "although": 1, "sometimes": 1, "at": 1, + "night": 1, "it": 2, "would": 4, "rain.": 1, "mind": 1, "rain": 1, + "because": 1, "cool": 1, "everything": 1, "down": 1, "allow": 1, + "us": 1, "sleep": 1, "peacefully.": 1, "Its": 2, "how": 1, + "affects": 1, "your": 1, "mood.": 1, "Who": 1, "have": 2, + "thought": 1, "that": 1, "could": 1, "write": 1, "a": 1, + "whole": 1, "essay": 1, "just": 1, "about": 1, "in": 1, + "grade.": 1, "kind": 1, "right": 1, "Youd": 1, "think": 1, + "for": 1, "such": 1, "an": 1, "interesting": 1, "person": 1, + "might": 1, "more": 1, "say": 1, "but": 1, "you": 1, "be": 1, "wrong.": 1, ] + + expect(result).to(equal(storyCount)) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble + +final class HaveCountTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (HaveCountTest) -> () throws -> Void)] { + return [ + ("testHaveCountForArray", testHaveCountForArray), + ("testHaveCountForDictionary", testHaveCountForDictionary), + ("testHaveCountForSet", testHaveCountForSet), + ] + } + + func testHaveCountForArray() { + expect([1, 2, 3]).to(haveCount(3)) + expect([1, 2, 3]).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Array with count 1, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Array with count 3, got 3\nActual Value: [1, 2, 3]") { + expect([1, 2, 3]).notTo(haveCount(3)) + } + } + + func testHaveCountForDictionary() { + let dictionary = ["1": 1, "2": 2, "3": 3] + expect(dictionary).to(haveCount(3)) + expect(dictionary).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Dictionary with count 1, got 3\nActual Value: \(stringify(dictionary))") { + expect(dictionary).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Dictionary with count 3, got 3" + + "\nActual Value: \(stringify(dictionary))") { + expect(dictionary).notTo(haveCount(3)) + } + } + + func testHaveCountForSet() { + let set = Set([1, 2, 3]) + expect(set).to(haveCount(3)) + expect(set).notTo(haveCount(1)) + + failsWithErrorMessage("expected to have Set with count 1, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).to(haveCount(1)) + } + + failsWithErrorMessage("expected to not have Set with count 3, got 3" + + "\nActual Value: \(stringify(set))") { + expect(set).notTo(haveCount(3)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..946e4cd --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift @@ -0,0 +1,84 @@ +import Foundation +import XCTest +import Nimble + +final class MatchErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchErrorTest) -> () throws -> Void)] { + return [ + ("testMatchErrorPositive", testMatchErrorPositive), + ("testMatchErrorNegative", testMatchErrorNegative), + ("testMatchNSErrorPositive", testMatchNSErrorPositive), + ("testMatchNSErrorNegative", testMatchNSErrorNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testDoesNotMatchNils", testDoesNotMatchNils), + ] + } + + func testMatchErrorPositive() { + expect(NimbleError.laugh).to(matchError(NimbleError.laugh)) + expect(NimbleError.laugh).to(matchError(NimbleError.self)) + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 1))) + + expect(NimbleError.laugh as Error).to(matchError(NimbleError.laugh)) + } + + func testMatchErrorNegative() { + expect(NimbleError.laugh).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh as Error).toNot(matchError(NimbleError.cry)) + expect(NimbleError.laugh).toNot(matchError(EquatableError.self)) + expect(EquatableError.parameterized(x: 1)).toNot(matchError(EquatableError.parameterized(x: 2))) + } + + func testMatchNSErrorPositive() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 0, userInfo: nil) + + expect(error1).to(matchError(error2)) + } + + func testMatchNSErrorNegative() { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + + expect(error1).toNot(matchError(error2)) + } + + func testMatchPositiveMessage() { + failsWithErrorMessage("expected to match error , got ") { + expect(EquatableError.parameterized(x: 1)).to(matchError(EquatableError.parameterized(x: 2))) + } + failsWithErrorMessage("expected to match error , got ") { + expect(NimbleError.laugh).to(matchError(NimbleError.cry)) + } + failsWithErrorMessage("expected to match error , got ") { + expect(CustomDebugStringConvertibleError.a).to(matchError(CustomDebugStringConvertibleError.b)) + } + + failsWithErrorMessage("expected to match error , got ") { + let error1 = NSError(domain: "err", code: 0, userInfo: nil) + let error2 = NSError(domain: "err", code: 1, userInfo: nil) + expect(error1).to(matchError(error2)) + } + } + + func testMatchNegativeMessage() { + failsWithErrorMessage("expected to not match error , got ") { + expect(NimbleError.laugh).toNot(matchError(NimbleError.laugh)) + } + + failsWithErrorMessage("expected to match error from type , got ") { + expect(NimbleError.laugh).to(matchError(EquatableError.self)) + } + } + + func testDoesNotMatchNils() { + failsWithErrorMessageForNil("expected to match error , got no error") { + expect(nil as Error?).to(matchError(NimbleError.laugh)) + } + + failsWithErrorMessageForNil("expected to not match error , got no error") { + expect(nil as Error?).toNot(matchError(NimbleError.laugh)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift @@ -0,0 +1,46 @@ +import XCTest +import Nimble + +final class MatchTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (MatchTest) -> () throws -> Void)] { + return [ + ("testMatchPositive", testMatchPositive), + ("testMatchNegative", testMatchNegative), + ("testMatchPositiveMessage", testMatchPositiveMessage), + ("testMatchNegativeMessage", testMatchNegativeMessage), + ("testMatchNils", testMatchNils), + ] + } + + func testMatchPositive() { + expect("11:14").to(match("\\d{2}:\\d{2}")) + } + + func testMatchNegative() { + expect("hello").toNot(match("\\d{2}:\\d{2}")) + } + + func testMatchPositiveMessage() { + let message = "expected to match <\\d{2}:\\d{2}>, got " + failsWithErrorMessage(message) { + expect("hello").to(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNegativeMessage() { + let message = "expected to not match <\\d{2}:\\d{2}>, got <11:14>" + failsWithErrorMessage(message) { + expect("11:14").toNot(match("\\d{2}:\\d{2}")) + } + } + + func testMatchNils() { + failsWithErrorMessageForNil("expected to match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).to(match("\\d{2}:\\d{2}")) + } + + failsWithErrorMessageForNil("expected to not match <\\d{2}:\\d{2}>, got ") { + expect(nil as String?).toNot(match("\\d{2}:\\d{2}")) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..ac7f9ec --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift @@ -0,0 +1,91 @@ +import XCTest +import Nimble +import Foundation + +final class PostNotificationTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PostNotificationTest) -> () throws -> Void)] { + return [ + ("testPassesWhenNoNotificationsArePosted", testPassesWhenNoNotificationsArePosted), + ("testPassesWhenExpectedNotificationIsPosted", testPassesWhenExpectedNotificationIsPosted), + ("testPassesWhenAllExpectedNotificationsArePosted", testPassesWhenAllExpectedNotificationsArePosted), + ("testFailsWhenNoNotificationsArePosted", testFailsWhenNoNotificationsArePosted), + ("testFailsWhenNotificationWithWrongNameIsPosted", testFailsWhenNotificationWithWrongNameIsPosted), + ("testFailsWhenNotificationWithWrongObjectIsPosted", testFailsWhenNotificationWithWrongObjectIsPosted), + ("testPassesWhenExpectedNotificationEventuallyIsPosted", testPassesWhenExpectedNotificationEventuallyIsPosted), + ] + } + + let notificationCenter = NotificationCenter() + + func testPassesWhenNoNotificationsArePosted() { + expect { + // no notifications here! + return nil + }.to(postNotifications(beEmpty(), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenExpectedNotificationIsPosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + self.notificationCenter.post(testNotification) + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + } + + func testPassesWhenAllExpectedNotificationsArePosted() { + let foo = NSNumber(value: 1) + let bar = NSNumber(value: 2) + let n1 = Notification(name: Notification.Name("Foo"), object: foo) + let n2 = Notification(name: Notification.Name("Bar"), object: bar) + expect { + self.notificationCenter.post(n1) + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1, n2]), fromNotificationCenter: notificationCenter)) + } + + func testFailsWhenNoNotificationsArePosted() { + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + failsWithErrorMessage("expected to equal <[\(testNotification)]>, got no notifications") { + expect { + // no notifications here! + return nil + }.to(postNotifications(equal([testNotification]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongNameIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: Notification.Name(n1.name.rawValue + "a"), object: nil) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testFailsWhenNotificationWithWrongObjectIsPosted() { + let n1 = Notification(name: Notification.Name("Foo"), object: nil) + let n2 = Notification(name: n1.name, object: NSObject()) + failsWithErrorMessage("expected to equal <[\(n1)]>, got <[\(n2)]>") { + expect { + self.notificationCenter.post(n2) + return nil + }.to(postNotifications(equal([n1]), fromNotificationCenter: self.notificationCenter)) + } + } + + func testPassesWhenExpectedNotificationEventuallyIsPosted() { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + let testNotification = Notification(name: Notification.Name("Foo"), object: nil) + expect { + deferToMainQueue { + self.notificationCenter.post(testNotification) + } + return nil + }.toEventually(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) + #else + print("\(#function) is missing because toEventually is not implement on this platform") + #endif + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..f62f633 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class RaisesExceptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (RaisesExceptionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testNegativeMatchesDoNotCallClosureWithoutException", testNegativeMatchesDoNotCallClosureWithoutException), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + var anException = NSException(name: NSExceptionName("laugh"), reason: "Lulz", userInfo: ["key": "value"]) + + func testPositiveMatches() { + expect { self.anException.raise() }.to(raiseException()) + expect { self.anException.raise() }.to(raiseException(named: "laugh")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz")) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + + func testPositiveMatchesWithClosures() { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName("laugh"))) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("lau")) + }) + + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("df")) + }) + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + failsWithErrorMessage("expected to raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "foo")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "bar")) + } + + failsWithErrorMessage( + "expected to raise exception with name with reason with userInfo <{k = v;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["k": "v"])) + } + + failsWithErrorMessage("expected to raise any exception, got no exception") { + expect { self.anException }.to(raiseException()) + } + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + failsWithErrorMessage("expected to raise exception with name with reason , got no exception") { + expect { self.anException }.to(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException(named: "bar", reason: "Lulz")) + } + failsWithErrorMessage("expected to not raise exception with name , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh")) + } + failsWithErrorMessage("expected to not raise exception with name with reason , got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz")) + } + + failsWithErrorMessage("expected to not raise exception with name with reason with userInfo <{key = value;}>, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"])) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutException() { + failsWithErrorMessage("expected to raise exception that satisfies block, got no exception") { + expect { self.anException }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName(rawValue: "foo"))) + }) + } + + failsWithErrorMessage("expected to raise exception with name that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "ha") { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to raise exception with name with reason with userInfo <{}> that satisfies block, got no exception") { + expect { self.anException }.to(raiseException(named: "foo", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + failsWithErrorMessage("expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.toNot(raiseException()) + } + } + + func testNegativeMatchesWithClosure() { + failsWithErrorMessage("expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }") { + expect { self.anException.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name.rawValue).to(equal("foo")) + }) + } + + let innerFailureMessage = "expected to begin with , got " + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "wrong") { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "laugh", reason: "Lulz", userInfo: ["key": "value"]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + + failsWithErrorMessage([innerFailureMessage, "expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: laugh), reason='Lulz', userInfo=[AnyHashable(\"key\"): \"value\"] }"]) { + expect { self.anException.raise() }.to(raiseException(named: "lol", reason: "Lulz", userInfo: [:]) { (exception: NSException) in + expect(exception.name.rawValue).to(beginWith("fo")) + }) + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift new file mode 100644 index 0000000..42ed892 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift @@ -0,0 +1,57 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAllOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAllOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAllOf", testSatisfyAllOf), + ("testOperatorAnd", testOperatorAnd), + ] + } + + func testSatisfyAllOf() { + expect(2).to(satisfyAllOf(equal(2), beLessThan(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAllOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAllOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAllOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").to(satisfyAllOf(contain("e"), beginWith("tur"))) + expect(82.0).to(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(82.00001))) + expect(false).toNot(satisfyAllOf(beTrue(), beFalse())) + expect(true).toNot(satisfyAllOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2") { + expect(2).to(satisfyAllOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match all of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, and {equal <[5, 6, 7]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAllOf(allPass("be less than 4", {$0 < 4}), equal([5, 6, 7]))) + } + failsWithErrorMessage( + "expected to not match all of: {be false}, got false") { + expect(false).toNot(satisfyAllOf(beFalse())) + } + failsWithErrorMessage( + "expected to not match all of: {be greater than <10.5>}, and {be less than <100.75>}, and {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAllOf(beGreaterThan(10.5), beLessThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorAnd() { + expect(2).to(equal(2) && beLessThan(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).to(beLessThan(3) && beGreaterThan(1)) +#else + expect(2 as NSNumber).to(beLessThan(3 as NSNumber) && beGreaterThan(1 as NSNumber)) +#endif + expect("turtle").to(contain("t") && endWith("tle")) + expect(82.0).to(beGreaterThan(10.5) && beLessThan(100.75)) + expect(false).to(beFalsy() && beFalse()) + expect(false).toNot(beTrue() && beFalse()) + expect(true).toNot(beTruthy() && beFalsy()) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift @@ -0,0 +1,56 @@ +import XCTest +import Nimble +import Foundation + +final class SatisfyAnyOfTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SatisfyAnyOfTest) -> () throws -> Void)] { + return [ + ("testSatisfyAnyOf", testSatisfyAnyOf), + ("testOperatorOr", testOperatorOr), + ] + } + + func testSatisfyAnyOf() { + expect(2).to(satisfyAnyOf(equal(2), equal(3))) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(satisfyAnyOf(equal(3), equal("turtles"))) +#else + expect(2 as NSNumber).toNot(satisfyAnyOf(equal(3 as NSNumber), equal("turtles" as NSString))) +#endif + expect([1, 2, 3]).to(satisfyAnyOf(equal([1, 2, 3]), allPass({$0 < 4}), haveCount(3))) + expect("turtle").toNot(satisfyAnyOf(contain("a"), endWith("magic"))) + expect(82.0).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + expect(false).to(satisfyAnyOf(beTrue(), beFalse())) + expect(true).to(satisfyAnyOf(beTruthy(), beFalsy())) + + failsWithErrorMessage( + "expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2") { + expect(2).to(satisfyAnyOf(equal(3), equal(4), equal(5))) + } + failsWithErrorMessage( + "expected to match one of: {all be less than 4, but failed first at element <5> in <[5, 6, 7]>}, or {equal <[1, 2, 3, 4]>}, got [5, 6, 7]") { + expect([5, 6, 7]).to(satisfyAnyOf(allPass("be less than 4", {$0 < 4}), equal([1, 2, 3, 4]))) + } + failsWithErrorMessage( + "expected to match one of: {be true}, got false") { + expect(false).to(satisfyAnyOf(beTrue())) + } + failsWithErrorMessage( + "expected to not match one of: {be less than <10.5>}, or {be greater than <100.75>}, or {be close to <50.1> (within 0.0001)}, got 50.10001") { + expect(50.10001).toNot(satisfyAnyOf(beLessThan(10.5), beGreaterThan(100.75), beCloseTo(50.1))) + } + } + + func testOperatorOr() { + expect(2).to(equal(2) || equal(3)) +#if SUPPORT_IMPLICIT_BRIDGING_CONVERSION + expect(2).toNot(equal(3) || equal("turtles")) +#else + expect(2 as NSNumber).toNot(equal(3 as NSNumber) || equal("turtles" as NSString)) +#endif + expect("turtle").toNot(contain("a") || endWith("magic")) + expect(82.0).toNot(beLessThan(10.5) || beGreaterThan(100.75)) + expect(false).to(beTrue() || beFalse()) + expect(true).to(beTruthy() || beFalsy()) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..68086e0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,62 @@ +import Foundation +import XCTest +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class ThrowAssertionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowAssertionTest) -> () throws -> Void)] { + return [ + ("testPositiveMatch", testPositiveMatch), + ("testErrorThrown", testErrorThrown), + ("testPostAssertionCodeNotRun", testPostAssertionCodeNotRun), + ("testNegativeMatch", testNegativeMatch), + ("testPositiveMessage", testPositiveMessage), + ("testNegativeMessage", testNegativeMessage), + ] + } + + func testPositiveMatch() { + expect { () -> Void in fatalError() }.to(throwAssertion()) + } + + func testErrorThrown() { + expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + } + + func testPostAssertionCodeNotRun() { + var reachedPoint1 = false + var reachedPoint2 = false + + expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true + }.to(throwAssertion()) + + expect(reachedPoint1) == true + expect(reachedPoint2) == false + } + + func testNegativeMatch() { + var reachedPoint1 = false + + expect { reachedPoint1 = true }.toNot(throwAssertion()) + + expect(reachedPoint1) == true + } + + func testPositiveMessage() { + failsWithErrorMessage("expected to throw an assertion") { + expect { () -> Void? in return }.to(throwAssertion()) + } + } + + func testNegativeMessage() { + failsWithErrorMessage("expected to not throw an assertion") { + expect { () -> Void in fatalError() }.toNot(throwAssertion()) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..f862992 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift @@ -0,0 +1,164 @@ +import XCTest +import Nimble + +enum NimbleError: Error { + case laugh + case cry +} + +enum EquatableError: Error { + case parameterized(x: Int) +} + +extension EquatableError: CustomDebugStringConvertible { + var debugDescription: String { + switch self { + case .parameterized(let x): + return "parameterized(x: \(x))" + } + } +} + +extension EquatableError: Equatable { +} + +func == (lhs: EquatableError, rhs: EquatableError) -> Bool { + switch (lhs, rhs) { + case (.parameterized(let l), .parameterized(let r)): + return l == r + } +} + +enum CustomDebugStringConvertibleError: Error { + case a + case b +} + +extension CustomDebugStringConvertibleError: CustomDebugStringConvertible { + var debugDescription: String { + return "code=\(_code)" + } +} + +final class ThrowErrorTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ThrowErrorTest) -> () throws -> Void)] { + return [ + ("testPositiveMatches", testPositiveMatches), + ("testPositiveMatchesWithClosures", testPositiveMatchesWithClosures), + ("testNegativeMatches", testNegativeMatches), + ("testPositiveNegatedMatches", testPositiveNegatedMatches), + ("testNegativeNegatedMatches", testNegativeNegatedMatches), + ("testNegativeMatchesDoNotCallClosureWithoutError", testNegativeMatchesDoNotCallClosureWithoutError), + ("testNegativeMatchesWithClosure", testNegativeMatchesWithClosure), + ] + } + + func testPositiveMatches() { + expect { throw NimbleError.laugh }.to(throwError()) + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh)) + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self)) + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 1))) + expect { throw EquatableError.parameterized(x: 1) }.toNot(throwError(EquatableError.parameterized(x: 2))) + } + + func testPositiveMatchesWithClosures() { + // Generic typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { error in + guard case EquatableError.parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Explicit typed closure + expect { throw EquatableError.parameterized(x: 42) }.to(throwError { (error: EquatableError) in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over errorType argument + expect { throw EquatableError.parameterized(x: 42) }.to(throwError(errorType: EquatableError.self) { error in + guard case .parameterized(let x) = error else { fail(); return } + expect(x) >= 1 + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).to(beginWith("Nim")) + }) + // Typed closure over error argument + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh) { (error: Error) in + expect(error._domain).toNot(beginWith("as")) + }) + } + + func testNegativeMatches() { + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Same case, different arguments + failsWithErrorMessage("expected to throw error , got ") { + expect { throw EquatableError.parameterized(x: 1) }.to(throwError(EquatableError.parameterized(x: 2))) + } + // Different case + failsWithErrorMessage("expected to throw error , got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry)) + } + // Different case with closure + failsWithErrorMessage("expected to throw error that satisfies block, got ") { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.cry) { _ in return }) + } + // Different case, implementing CustomDebugStringConvertible + failsWithErrorMessage("expected to throw error , got ") { + expect { throw CustomDebugStringConvertibleError.a }.to(throwError(CustomDebugStringConvertibleError.b)) + } + } + + func testPositiveNegatedMatches() { + // No error at all + expect { return }.toNot(throwError()) + // Different case + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.cry)) + } + + func testNegativeNegatedMatches() { + // No error at all + failsWithErrorMessage("expected to not throw any error, got ") { + expect { throw NimbleError.laugh }.toNot(throwError()) + } + // Different error + failsWithErrorMessage("expected to not throw error , got ") { + expect { throw NimbleError.laugh }.toNot(throwError(NimbleError.laugh)) + } + } + + func testNegativeMatchesDoNotCallClosureWithoutError() { + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError { _ in + fail() + }) + } + + failsWithErrorMessage("expected to throw error that satisfies block, got no error") { + expect { return }.to(throwError(NimbleError.laugh) { _ in + fail() + }) + } + } + + func testNegativeMatchesWithClosure() { + let moduleName = "NimbleTests" + let innerFailureMessage = "expected to equal , got <\(moduleName).NimbleError>" + let closure = { (error: Error) in + expect(error._domain).to(equal("foo")) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error from type that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(errorType: NimbleError.self, closure: closure)) + } + + failsWithErrorMessage([innerFailureMessage, "expected to throw error that satisfies block, got "]) { + expect { throw NimbleError.laugh }.to(throwError(NimbleError.laugh, closure: closure)) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift new file mode 100644 index 0000000..dde999a --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift @@ -0,0 +1,36 @@ +import XCTest +import Nimble + +final class ToSucceedTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ToSucceedTest) -> () throws -> Void)] { + return [ + ("testToSucceed", testToSucceed), + ] + } + + func testToSucceed() { + expect({ + return .succeeded + }).to(succeed()) + + expect({ + return .failed(reason: "") + }).toNot(succeed()) + + failsWithErrorMessageForNil("expected a closure, got ") { + expect(nil as (() -> ToSucceedResult)?).to(succeed()) + } + + failsWithErrorMessage("expected to succeed, got because ") { + expect({ + .failed(reason: "something went wrong") + }).to(succeed()) + } + + failsWithErrorMessage("expected to not succeed, got ") { + expect({ + return .succeeded + }).toNot(succeed()) + } + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift new file mode 100644 index 0000000..ce8181b --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift @@ -0,0 +1,128 @@ +import Foundation +import XCTest +import Nimble + +final class SynchronousTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SynchronousTest) -> () throws -> Void)] { + return [ + ("testFailAlwaysFails", testFailAlwaysFails), + ("testUnexpectedErrorsThrownFails", testUnexpectedErrorsThrownFails), + ("testToMatchesIfMatcherReturnsTrue", testToMatchesIfMatcherReturnsTrue), + ("testToProvidesActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpression", testToProvidesActualValueExpression), + ("testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToMatchAgainstLazyProperties", testToMatchAgainstLazyProperties), + ("testToNotMatchesIfMatcherReturnsTrue", testToNotMatchesIfMatcherReturnsTrue), + ("testToNotProvidesActualValueExpression", testToNotProvidesActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpression", testToNotProvidesAMemoizedActualValueExpression), + ("testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl", testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl), + ("testToNotNegativeMatches", testToNotNegativeMatches), + ("testNotToMatchesLikeToNot", testNotToMatchesLikeToNot), + ] + } + + class Error: Swift.Error {} + let errorToThrow = Error() + + private func doThrowError() throws -> Int { + throw errorToThrow + } + + func testFailAlwaysFails() { + failsWithErrorMessage("My error message") { + fail("My error message") + } + failsWithErrorMessage("fail() always fails") { + fail() + } + } + + func testUnexpectedErrorsThrownFails() { + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.to(equal(1)) + } + failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toNot(equal(1)) + } + } + + func testToMatchesIfMatcherReturnsTrue() { + expect(1).to(MatcherFunc { _, _ in true }) + expect {1}.to(MatcherFunc { _, _ in true }) + } + + func testToProvidesActualValueExpression() { + var value: Int? + expect(1).to(MatcherFunc { expr, _ in value = try expr.evaluate(); return true }) + expect(value).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.to(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return true + }) + expect(callCount).to(equal(1)) + } + + func testToMatchAgainstLazyProperties() { + expect(ObjectWithLazyProperty().value).to(equal("hello")) + expect(ObjectWithLazyProperty().value).toNot(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).to(equal("world")) + expect(ObjectWithLazyProperty().anotherValue).toNot(equal("hello")) + } + + // repeated tests from to() for toNot() + func testToNotMatchesIfMatcherReturnsTrue() { + expect(1).toNot(MatcherFunc { _, _ in false }) + expect {1}.toNot(MatcherFunc { _, _ in false }) + } + + func testToNotProvidesActualValueExpression() { + var value: Int? + expect(1).toNot(MatcherFunc { expr, _ in value = try expr.evaluate(); return false }) + expect(value).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpression() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + _ = try expr.evaluate() + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { + var callCount = 0 + expect { callCount += 1 }.toNot(MatcherFunc { expr, _ in + expect(callCount).to(equal(0)) + _ = try expr.evaluate() + return false + }) + expect(callCount).to(equal(1)) + } + + func testToNotNegativeMatches() { + failsWithErrorMessage("expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }) + } + } + + func testNotToMatchesLikeToNot() { + expect(1).notTo(MatcherFunc { _, _ in false }) + } +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift @@ -0,0 +1,64 @@ +import XCTest +import Nimble + +final class UserDescriptionTest: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (UserDescriptionTest) -> () throws -> Void)] { + return [ + ("testToMatcher_CustomFailureMessage", testToMatcher_CustomFailureMessage), + ("testNotToMatcher_CustomFailureMessage", testNotToMatcher_CustomFailureMessage), + ("testToNotMatcher_CustomFailureMessage", testToNotMatcher_CustomFailureMessage), + ("testToEventuallyMatch_CustomFailureMessage", testToEventuallyMatch_CustomFailureMessage), + ("testToEventuallyNotMatch_CustomFailureMessage", testToEventuallyNotMatch_CustomFailureMessage), + ("testToNotEventuallyMatch_CustomFailureMessage", testToNotEventuallyMatch_CustomFailureMessage), + ] + } + + func testToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to match, got <1>") { + expect(1).to(MatcherFunc { _, _ in false }, description: "These aren't equal!") + } + } + + func testNotToMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).notTo(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToNotMatcher_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't equal!\n" + + "expected to not match, got <1>") { + expect(1).toNot(MatcherFunc { _, _ in true }, description: "These aren't equal!") + } + } + + func testToEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These aren't eventually equal!\n" + + "expected to eventually equal <1>, got <0>") { + expect { 0 }.toEventually(equal(1), description: "These aren't eventually equal!") + } + } + + func testToEventuallyNotMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + + func testToNotEventuallyMatch_CustomFailureMessage() { + failsWithErrorMessage( + "These are eventually equal!\n" + + "expected to eventually not equal <1>, got <1>") { + expect { 1 }.toEventuallyNot(equal(1), description: "These are eventually equal!") + } + } + +} diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h @@ -0,0 +1,15 @@ +@import Nimble; +#import "NimbleTests-Swift.h" + +// Use this when you want to verify the failure message for when an expectation fails +#define expectFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessage:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + +#define expectFailureMessages(MSGS, BLOCK) \ +[NimbleHelper expectFailureMessages:(MSGS) block:(BLOCK) file:@(__FILE__) line:__LINE__]; + + +// Use this when you want to verify the failure message with the nil message postfixed +// to it: " (use beNil() to match nils)" +#define expectNilFailureMessage(MSG, BLOCK) \ +[NimbleHelper expectFailureMessageForNil:(MSG) block:(BLOCK) file:@(__FILE__) line:__LINE__]; diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..4bdc021 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m @@ -0,0 +1,38 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAllPassTest : XCTestCase + +@end + +@implementation ObjCAllPassTest + +- (void)testPositiveMatches { + expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); + expect(@[@1, @2, @3,@4]).toNot(allPass(beGreaterThan(@5))); + + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).to(allPass(beLessThan(@5))); + expect([NSSet setWithArray:@[@1, @2, @3,@4]]).toNot(allPass(beGreaterThan(@5))); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to all be less than <3>, but failed first at element" + " <3> in <[1, 2, 3, 4]>", ^{ + expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@3))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect(@[@1, @2, @3, @4]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"expected to not all be less than <5>", ^{ + expect([NSSet setWithArray:@[@1, @2, @3, @4]]).toNot(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).to(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass can only be used with types which implement NSFastEnumeration " + "(NSArray, NSSet, ...), and whose elements subclass NSObject, got <3>", ^{ + expect(@3).toNot(allPass(beLessThan(@5))); + }); +} +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m @@ -0,0 +1,55 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCAsyncTest : XCTestCase + +@end + +@implementation ObjCAsyncTest + +- (void)testAsync { + __block id obj = @1; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = nil; + }); + expect(obj).toEventually(beNil()); +} + + +- (void)testAsyncWithCustomTimeout { + __block id obj = nil; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + obj = @1; + }); + expect(obj).withTimeout(5).toEventuallyNot(beNil()); +} + +- (void)testAsyncCallback { + waitUntil(^(void (^done)(void)){ + done(); + }); + + expectFailureMessage(@"Waited more than 1.0 second", ^{ + waitUntil(^(void (^done)(void)){ /* ... */ }); + }); + + expectFailureMessage(@"Waited more than 0.01 seconds", ^{ + waitUntilTimeout(0.01, ^(void (^done)(void)){ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [NSThread sleepForTimeInterval:0.1]; + done(); + }); + }); + }); + + expectFailureMessage(@"expected to equal , got ", ^{ + waitUntil(^(void (^done)(void)){ + [NSThread sleepForTimeInterval:0.1]; + expect(@"hello").to(equal(@"goodbye")); + done(); + }); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeAnInstanceOfTest : XCTestCase +@end + +@implementation ObjCBeAnInstanceOfTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beAnInstanceOf([NSNull class])); + expect(@1).toNot(beAnInstanceOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be an instance of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAnInstanceOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAnInstanceOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be an instance of NSNull, got ", ^{ + expect(nil).to(beAnInstanceOf([NSNull class])); + }); + + expectNilFailureMessage(@"expected to not be an instance of NSNull, got ", ^{ + expect(nil).toNot(beAnInstanceOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeCloseToTest : XCTestCase + +@end + +@implementation ObjCBeCloseToTest + +- (void)testPositiveMatches { + expect(@1.2).to(beCloseTo(@1.2001)); + expect(@1.2).to(beCloseTo(@2).within(10)); + expect(@2).toNot(beCloseTo(@1)); + expect(@1.00001).toNot(beCloseTo(@1).within(0.00000001)); + + expect(1.2).to(beCloseTo(1.2001)); + expect(1.2).to(beCloseTo(2).within(10)); + expect(2).toNot(beCloseTo(1)); + expect(1.00001).toNot(beCloseTo(1).within(0.00000001)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(@1).to(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(@(0.0001)).toNot(beCloseTo(@0)); + }); + expectFailureMessage(@"expected to be close to <0> (within 0.001), got <1>", ^{ + expect(1).to(beCloseTo(0)); + }); + expectFailureMessage(@"expected to not be close to <0> (within 0.001), got <0.0001>", ^{ + expect(0.0001).toNot(beCloseTo(0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be close to <0> (within 0.001), got ", ^{ + expect(nil).to(beCloseTo(@0)); + }); + expectNilFailureMessage(@"expected to not be close to <0> (within 0.001), got ", ^{ + expect(nil).toNot(beCloseTo(@0)); + }); +} + + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..5e803cb --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m @@ -0,0 +1,89 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeEmptyTest : XCTestCase +@end + +@implementation ObjCBeEmptyTest + +- (void)testPositiveMatches { + expect(@[]).to(beEmpty()); + expect(@"").to(beEmpty()); + expect(@{}).to(beEmpty()); + expect([NSSet set]).to(beEmpty()); + expect([NSIndexSet indexSet]).to(beEmpty()); + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]).to(beEmpty()); + + expect(@[@1, @2]).toNot(beEmpty()); + expect(@"a").toNot(beEmpty()); + expect(@{@"key": @"value"}).toNot(beEmpty()); + expect([NSSet setWithObject:@1]).toNot(beEmpty()); + expect([NSIndexSet indexSetWithIndex:1]).toNot(beEmpty()); + + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + expect(table).toNot(beEmpty()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be empty, got ", ^{ + expect(@"foo").to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect(@[@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{key = value;}>", ^{ + expect(@{@"key": @"value"}).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <{(1)}>", ^{ + expect([NSSet setWithObject:@1]).to(beEmpty()); + }); + expectFailureMessage(@"expected to be empty, got <(1)>", ^{ + expect([NSIndexSet indexSetWithIndex:1]).to(beEmpty()); + }); + NSHashTable *table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + NSString *tableString = [[table description] stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be empty, got <%@>", tableString]), ^{ + expect(table).to(beEmpty()); + }); + + expectFailureMessage(@"expected to not be empty, got <>", ^{ + expect(@"").toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect(@[]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{}>", ^{ + expect(@{}).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <{()}>", ^{ + expect([NSSet set]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <()>", ^{ + expect([NSIndexSet indexSet]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got ", ^{ + expect([NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]).toNot(beEmpty()); + }); +} + +- (void)testItDoesNotMatchNil { + expectNilFailureMessage(@"expected to be empty, got ", ^{ + expect(nil).to(beEmpty()); + }); + expectNilFailureMessage(@"expected to not be empty, got ", ^{ + expect(nil).toNot(beEmpty()); + }); +} + +- (void)testItReportsTypesItMatchesAgainst { + expectFailureMessage(@"expected to be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).to(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings), got __NSCFNumber type", ^{ + expect(@1).toNot(beEmpty()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m @@ -0,0 +1,46 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalseTest : XCTestCase + +@end + +@implementation ObjCBeFalseTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalse()); + expect(@YES).toNot(beFalse()); + + expect(false).to(beFalse()); + expect(true).toNot(beFalse()); + + expect(NO).to(beFalse()); + expect(YES).toNot(beFalse()); + + expect(10).toNot(beFalse()); +} + +- (void)testNegativeMatches { + expectNilFailureMessage(@"expected to be false, got ", ^{ + expect(nil).to(beFalse()); + }); + expectNilFailureMessage(@"expected to not be false, got ", ^{ + expect(nil).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(true).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(false).toNot(beFalse()); + }); + + expectFailureMessage(@"expected to be false, got <1>", ^{ + expect(YES).to(beFalse()); + }); + expectFailureMessage(@"expected to not be false, got <0>", ^{ + expect(NO).toNot(beFalse()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m @@ -0,0 +1,58 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeFalsyTest : XCTestCase + +@end + +@implementation ObjCBeFalsyTest + +- (void)testPositiveMatches { + expect(@NO).to(beFalsy()); + expect(@YES).toNot(beFalsy()); + expect(nil).to(beFalsy()); + + expect(true).toNot(beFalsy()); + expect(false).to(beFalsy()); + + expect(YES).toNot(beFalsy()); + expect(NO).to(beFalsy()); + + expect(10).toNot(beFalsy()); + expect(0).to(beFalsy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to not be falsy, got ", ^{ + expect(nil).toNot(beFalsy()); + }); + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(@1).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(@NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(true).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(false).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <1>", ^{ + expect(YES).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(NO).toNot(beFalsy()); + }); + + expectFailureMessage(@"expected to be falsy, got <10>", ^{ + expect(10).to(beFalsy()); + }); + expectFailureMessage(@"expected to not be falsy, got <0>", ^{ + expect(0).toNot(beFalsy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..28862ba --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m @@ -0,0 +1,44 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThanOrEqualTo(@2)); + expect(@2).toNot(beGreaterThanOrEqualTo(@3)); + expect(2).to(beGreaterThanOrEqualTo(0)); + expect(2).to(beGreaterThanOrEqualTo(2)); + expect(2).toNot(beGreaterThanOrEqualTo(3)); + expect(2.5).to(beGreaterThanOrEqualTo(2)); + expect(2.5).to(beGreaterThanOrEqualTo(2.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThanOrEqualTo(@0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThanOrEqualTo(@(1))); + }); + expectFailureMessage(@"expected to be greater than or equal to <0>, got <-1>", ^{ + expect(-1).to(beGreaterThanOrEqualTo(0)); + }); + expectFailureMessage(@"expected to not be greater than or equal to <1>, got <2>", ^{ + expect(2).toNot(beGreaterThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than or equal to <-1>, got ", ^{ + expect(nil).to(beGreaterThanOrEqualTo(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than or equal to <1>, got ", ^{ + expect(nil).toNot(beGreaterThanOrEqualTo(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..5a57d54 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeGreaterThanTest : XCTestCase + +@end + +@implementation ObjCBeGreaterThanTest + +- (void)testPositiveMatches { + expect(@2).to(beGreaterThan(@1)); + expect(@2).toNot(beGreaterThan(@2)); + expect(@2).to(beGreaterThan(0)); + expect(@2).toNot(beGreaterThan(2)); + expect(2.5).to(beGreaterThan(1.5)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(@(-1)).to(beGreaterThan(@(0))); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(@2).toNot(beGreaterThan(@(1))); + }); + expectFailureMessage(@"expected to be greater than <0>, got <-1>", ^{ + expect(-1).to(beGreaterThan(0)); + }); + expectFailureMessage(@"expected to not be greater than <1>, got <2>", ^{ + expect(2).toNot(beGreaterThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be greater than <-1>, got ", ^{ + expect(nil).to(beGreaterThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be greater than <1>, got ", ^{ + expect(nil).toNot(beGreaterThan(@(1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m @@ -0,0 +1,68 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeIdenticalToTest : XCTestCase + +@end + +@implementation ObjCBeIdenticalToTest + +- (void)testPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(beIdenticalTo([NSNull null])); + expect(@2).toNot(beIdenticalTo(@3)); +} + +- (void)testNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(beIdenticalTo(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(beIdenticalTo(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(beIdenticalTo(obj)); + }); +} + +- (void)testAliasPositiveMatches { + NSNull *obj = [NSNull null]; + expect(obj).to(be([NSNull null])); + expect(@2).toNot(be(@3)); +} + +- (void)testAliasNegativeMatches { + NSNull *obj = [NSNull null]; + expectFailureMessage(([NSString stringWithFormat:@"expected to be identical to <%p>, got <%p>", obj, @2]), ^{ + expect(@2).to(be(obj)); + }); + expectFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got <%p>", obj, obj]), ^{ + expect(obj).toNot(be(obj)); + }); +} + +- (void)testAliasNilMatches { + NSNull *obj = [NSNull null]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + expectNilFailureMessage(@"expected to be identical to nil, got nil", ^{ + expect(nil).to(be(nil)); + }); +#pragma clang diagnostic pop + expectNilFailureMessage(([NSString stringWithFormat:@"expected to not be identical to <%p>, got nil", obj]), ^{ + expect(nil).toNot(be(obj)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m @@ -0,0 +1,34 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeKindOfTest : XCTestCase + +@end + +@implementation ObjCBeKindOfTest + +- (void)testPositiveMatches { + NSMutableArray *array = [NSMutableArray array]; + expect(array).to(beAKindOf([NSArray class])); + expect(@1).toNot(beAKindOf([NSNull class])); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be a kind of NSNull, got <__NSCFNumber instance>", ^{ + expect(@1).to(beAKindOf([NSNull class])); + }); + expectFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect([NSNull null]).toNot(beAKindOf([NSNull class])); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be a kind of NSNull, got ", ^{ + expect(nil).to(beAKindOf([NSNull class])); + }); + expectNilFailureMessage(@"expected to not be a kind of NSNull, got ", ^{ + expect(nil).toNot(beAKindOf([NSNull class])); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m @@ -0,0 +1,43 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanOrEqualToTest : XCTestCase + +@end + +@implementation ObjCBeLessThanOrEqualToTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThanOrEqualTo(@2)); + expect(@2).toNot(beLessThanOrEqualTo(@1)); + expect(2).to(beLessThanOrEqualTo(2)); + expect(2).toNot(beLessThanOrEqualTo(1)); + expect(2).toNot(beLessThanOrEqualTo(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(@2).to(beLessThanOrEqualTo(@1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(@1).toNot(beLessThanOrEqualTo(@1)); + }); + + expectFailureMessage(@"expected to be less than or equal to <1>, got <2>", ^{ + expect(2).to(beLessThanOrEqualTo(1)); + }); + expectFailureMessage(@"expected to not be less than or equal to <1>, got <1>", ^{ + expect(1).toNot(beLessThanOrEqualTo(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than or equal to <1>, got ", ^{ + expect(nil).to(beLessThanOrEqualTo(@1)); + }); + expectNilFailureMessage(@"expected to not be less than or equal to <-1>, got ", ^{ + expect(nil).toNot(beLessThanOrEqualTo(@(-1))); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..9750641 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m @@ -0,0 +1,42 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeLessThanTest : XCTestCase + +@end + +@implementation ObjCBeLessThanTest + +- (void)testPositiveMatches { + expect(@2).to(beLessThan(@3)); + expect(@2).toNot(beLessThan(@2)); + expect(2).to(beLessThan(3)); + expect(2).toNot(beLessThan(2)); + expect(2).toNot(beLessThan(0)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(@(1)).to(beLessThan(@0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(@0).toNot(beLessThan(@1)); + }); + expectFailureMessage(@"expected to be less than <0>, got <1>", ^{ + expect(1).to(beLessThan(0)); + }); + expectFailureMessage(@"expected to not be less than <1>, got <0>", ^{ + expect(0).toNot(beLessThan(1)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to be less than <-1>, got ", ^{ + expect(nil).to(beLessThan(@(-1))); + }); + expectNilFailureMessage(@"expected to not be less than <1>, got ", ^{ + expect(nil).toNot(beLessThan(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m @@ -0,0 +1,24 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeNilTest : XCTestCase + +@end + +@implementation ObjCBeNilTest + +- (void)testPositiveMatches { + expect(nil).to(beNil()); + expect(@NO).toNot(beNil()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be nil, got <1>", ^{ + expect(@1).to(beNil()); + }); + expectFailureMessage(@"expected to not be nil, got ", ^{ + expect(nil).toNot(beNil()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m @@ -0,0 +1,47 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTrueTest : XCTestCase + +@end + +@implementation ObjCBeTrueTest + +- (void)testPositiveMatches { + expect(@YES).to(beTrue()); + expect(@NO).toNot(beTrue()); + expect(nil).toNot(beTrue()); + + expect(true).to(beTrue()); + expect(false).toNot(beTrue()); + + expect(YES).to(beTrue()); + expect(NO).toNot(beTrue()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(@NO).to(beTrue()); + }); + expectFailureMessage(@"expected to be true, got ", ^{ + expect(nil).to(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(false).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(true).toNot(beTrue()); + }); + + expectFailureMessage(@"expected to be true, got <0>", ^{ + expect(NO).to(beTrue()); + }); + + expectFailureMessage(@"expected to not be true, got <1>", ^{ + expect(YES).toNot(beTrue()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m @@ -0,0 +1,55 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeTruthyTest : XCTestCase + +@end + +@implementation ObjCBeTruthyTest + +- (void)testPositiveMatches { + expect(@YES).to(beTruthy()); + expect(@NO).toNot(beTruthy()); + expect(nil).toNot(beTruthy()); + + expect(true).to(beTruthy()); + expect(false).toNot(beTruthy()); + + expect(YES).to(beTruthy()); + expect(NO).toNot(beTruthy()); + + expect(10).to(beTruthy()); + expect(0).toNot(beTruthy()); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to be truthy, got ", ^{ + expect(nil).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(@1).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(@NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(false).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(true).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(NO).to(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <1>", ^{ + expect(YES).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to not be truthy, got <10>", ^{ + expect(10).toNot(beTruthy()); + }); + expectFailureMessage(@"expected to be truthy, got <0>", ^{ + expect(0).to(beTruthy()); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCBeginWithTest : XCTestCase + +@end + +@implementation ObjCBeginWithTest + +- (void)testPositiveMatches { + expect(@"hello world!").to(beginWith(@"hello")); + expect(@"hello world!").toNot(beginWith(@"world")); + + NSArray *array = @[@1, @2]; + expect(array).to(beginWith(@1)); + expect(array).toNot(beginWith(@2)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to begin with , got ", ^{ + expect(@"foo").to(beginWith(@"bar")); + }); + expectFailureMessage(@"expected to not begin with , got ", ^{ + expect(@"foo").toNot(beginWith(@"foo")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to begin with <1>, got ", ^{ + expect(nil).to(beginWith(@1)); + }); + expectNilFailureMessage(@"expected to not begin with <1>, got ", ^{ + expect(nil).toNot(beginWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfyingTest.m @@ -0,0 +1,64 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainElementSatisfyingTest : XCTestCase + +@end + +@implementation ObjCContainElementSatisfyingTest + +- (void)testPassingMatches { + NSArray *orderIndifferentArray = @[@1, @2, @3]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + orderIndifferentArray = @[@3, @1, @2]; + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@1]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + expect(orderIndifferentArray).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + + NSSet *orderIndifferentSet = [NSSet setWithObjects:@"turtle test", @"turtle assessment", nil]; + expect(orderIndifferentSet).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"turtle assessment"]; + })); +} + +- (void)testFailingMatches { + expectFailureMessage(@"expected to find object in collection that satisfies predicate", ^{ + expect(@[@1]).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@2]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((nil)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); + expectFailureMessage(@"containElementSatisfying must be provided an NSFastEnumeration object", ^{ + expect((@3)).to(containElementSatisfying(^BOOL(id object) { + return [object isEqualToNumber:@3]; + })); + }); +} + +- (void)testNegativeCases { + NSArray *orderIndifferentArray = @[@"puppies", @"kittens", @"turtles"]; + expect(orderIndifferentArray).toNot(containElementSatisfying(^BOOL(id object) { + return [object isEqualToString:@"armadillos"]; + })); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..8b954fe --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m @@ -0,0 +1,67 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCContainTest : XCTestCase + +@end + +@implementation ObjCContainTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1)); + expect(array).toNot(contain(@"HI")); + expect(@"String").to(contain(@"Str")); + expect(@"Other").toNot(contain(@"Str")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to contain <3>, got <(1, 2)>", ^{ + expect((@[@1, @2])).to(contain(@3)); + }); + expectFailureMessage(@"expected to not contain <2>, got <(1, 2)>", ^{ + expect((@[@1, @2])).toNot(contain(@2)); + }); + + expectFailureMessage(@"expected to contain , got ", ^{ + expect(@"la").to(contain(@"hi")); + }); + expectFailureMessage(@"expected to not contain , got ", ^{ + expect(@"hihihi").toNot(contain(@"hi")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to contain <3>, got ", ^{ + expect(nil).to(contain(@3)); + }); + expectNilFailureMessage(@"expected to not contain <3>, got ", ^{ + expect(nil).toNot(contain(@3)); + }); + + expectNilFailureMessage(@"expected to contain , got ", ^{ + expect(nil).to(contain(@"hi")); + }); + expectNilFailureMessage(@"expected to not contain , got ", ^{ + expect(nil).toNot(contain(@"hi")); + }); +} + +- (void)testVariadicArguments { + NSArray *array = @[@1, @2]; + expect(array).to(contain(@1, @2)); + expect(array).toNot(contain(@"HI", @"whale")); + expect(@"String").to(contain(@"Str", @"ng")); + expect(@"Other").toNot(contain(@"Str", @"Oth")); + + + expectFailureMessage(@"expected to contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).to(contain(@"a", @"bar")); + }); + + expectFailureMessage(@"expected to not contain , got <(a, b, c)>", ^{ + expect(@[@"a", @"b", @"c"]).toNot(contain(@"a", @"b")); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m @@ -0,0 +1,37 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEndWithTest : XCTestCase + +@end + +@implementation ObjCEndWithTest + +- (void)testPositiveMatches { + NSArray *array = @[@1, @2]; + expect(@"hello world!").to(endWith(@"world!")); + expect(@"hello world!").toNot(endWith(@"hello")); + expect(array).to(endWith(@2)); + expect(array).toNot(endWith(@1)); + expect(@1).toNot(contain(@"foo")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to end with , got ", ^{ + expect(@"hello world!").to(endWith(@"?")); + }); + expectFailureMessage(@"expected to not end with , got ", ^{ + expect(@"hello world!").toNot(endWith(@"!")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to end with <1>, got ", ^{ + expect(nil).to(endWith(@1)); + }); + expectNilFailureMessage(@"expected to not end with <1>, got ", ^{ + expect(nil).toNot(endWith(@1)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..9d1361e --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m @@ -0,0 +1,94 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCEqualTest : XCTestCase + +@end + +@implementation ObjCEqualTest + +- (void)testPositiveMatches { + expect(@1).to(equal(@1)); + expect(@1).toNot(equal(@2)); + expect(@1).notTo(equal(@2)); + expect(@"hello").to(equal(@"hello")); + expect("hello").to(equal("hello")); + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 10))); + expect(NSMakeRange(0, 10)).toNot(equal(NSMakeRange(0, 5))); + expect((NSInteger)1).to(equal((NSInteger)1)); + expect((NSInteger)1).toNot(equal((NSInteger)2)); + expect((NSUInteger)1).to(equal((NSUInteger)1)); + expect((NSUInteger)1).toNot(equal((NSUInteger)2)); + expect(0).to(equal(0)); + expect(1).to(equal(1)); + expect(1).toNot(equal(2)); + expect(1.0).to(equal(1.0)); // Note: not recommended, use beCloseTo() instead + expect(1.0).toNot(equal(2.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).to(equal((float)1.0)); // Note: not recommended, use beCloseTo() instead + expect((float)1.0).toNot(equal((float)2.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).to(equal((double)1.0)); // Note: not recommended, use beCloseTo() instead + expect((double)1.0).toNot(equal((double)2.0)); // Note: not recommended, use beCloseTo() instead + expect((long long)1).to(equal((long long)1)); + expect((long long)1).toNot(equal((long long)2)); + expect((unsigned long long)1).to(equal((unsigned long long)1)); + expect((unsigned long long)1).toNot(equal((unsigned long long)2)); +} + +- (void)testNimbleCurrentlyBoxesNumbersWhichAllowsImplicitTypeConversions { + expect(1).to(equal(1.0)); + expect((long long)1).to(equal((unsigned long long)1)); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(@1).to(equal(@2)); + }); + expectFailureMessage(@"expected to not equal <1>, got <1>", ^{ + expect(@1).toNot(equal(@1)); + }); + expectFailureMessage(@"expected to not equal , got ", ^{ + expect("bar").toNot(equal("bar")); + }); + expectFailureMessage(@"expected to equal , got ", ^{ + expect(NSMakeRange(0, 10)).to(equal(NSMakeRange(0, 5))); + }); + + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSInteger)1).to(equal((NSInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((NSUInteger)1).to(equal((NSUInteger)2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1).to(equal(2)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect(1.0).to(equal(2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((float)1.0).to(equal((float)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((double)1.0).to(equal((double)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((long long)1.0).to(equal((long long)2.0)); + }); + expectFailureMessage(@"expected to equal <2>, got <1>", ^{ + expect((unsigned long long)1.0).to(equal((unsigned long long)2.0)); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(NULL).to(equal(NULL)); + }); + expectNilFailureMessage(@"expected to equal , got ", ^{ + expect(nil).to(equal(nil)); + }); + expectNilFailureMessage(@"expected to not equal , got ", ^{ + expect(nil).toNot(equal(nil)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCountTest.m @@ -0,0 +1,174 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCHaveCountTest : XCTestCase + +@end + +@implementation ObjCHaveCountTest + +- (void)testHaveCountForNSArray { + expect(@[@1, @2, @3]).to(haveCount(@3)); + expect(@[@1, @2, @3]).notTo(haveCount(@1)); + + expect(@[]).to(haveCount(@0)); + expect(@[@1]).notTo(haveCount(@0)); + + expect(@[@1, @2, @3]).to(haveCount(3)); + expect(@[@1, @2, @3]).notTo(haveCount(1)); + + expect(@[]).to(haveCount(0)); + expect(@[@1]).notTo(haveCount(0)); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSArray with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSArray with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(@[@1, @2, @3]).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSDictionary { + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@1)); + + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(3)); + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSDictionary with count 1, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSDictionary with count 3, got 3\nActual Value: {1 = 1;2 = 2;3 = 3;}", ^{ + expect(@{@"1":@1, @"2":@2, @"3":@3}).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSHashtable { + NSHashTable *const table = [NSHashTable hashTableWithOptions:NSPointerFunctionsStrongMemory]; + [table addObject:@1]; + [table addObject:@2]; + [table addObject:@3]; + + expect(table).to(haveCount(@3)); + expect(table).notTo(haveCount(@1)); + + expect(table).to(haveCount(3)); + expect(table).notTo(haveCount(1)); + + NSString *msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(@1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(@3)); + }); + + + msg = [NSString stringWithFormat: + @"expected to have NSHashTable {[2] 2[12] 1[13] 3}with count 1, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).to(haveCount(1)); + }); + + msg = [NSString stringWithFormat: + @"expected to not have NSHashTable {[2] 2[12] 1[13] 3}with count 3, got 3\nActual Value: %@", + [table.description stringByReplacingOccurrencesOfString:@"\n" withString:@""]]; + expectFailureMessage(msg, ^{ + expect(table).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSSet { + NSSet *const set = [NSSet setWithArray:@[@1, @2, @3]]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSSet with count 1, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSSet with count 3, got 3\nActual Value: {(3,1,2)}", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForNSIndexSet { + NSIndexSet *const set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + + expect(set).to(haveCount(@3)); + expect(set).notTo(haveCount(@1)); + expect(set).to(haveCount(3)); + expect(set).notTo(haveCount(1)); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(@1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(@3)); + }); + + expectFailureMessage(@"expected to have NSIndexSet with count 1, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).to(haveCount(1)); + }); + + expectFailureMessage(@"expected to not have NSIndexSet with count 3, got 3\nActual Value: (1, 2, 3)", ^{ + expect(set).notTo(haveCount(3)); + }); +} + +- (void)testHaveCountForUnsupportedTypes { + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(@6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFConstantString", ^{ + expect(@"string").to(haveCount(6)); + }); + + expectFailureMessage(@"expected to get type of NSArray, NSSet, NSDictionary, or NSHashTable, got __NSCFNumber", ^{ + expect(@1).to(haveCount(6)); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m @@ -0,0 +1,33 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCMatchTest : XCTestCase + +@end + +@implementation ObjCMatchTest + +- (void)testPositiveMatches { + expect(@"11:14").to(match(@"\\d{2}:\\d{2}")); + expect(@"hello").toNot(match(@"\\d{2}:\\d{2}")); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(@"hello").to(match(@"\\d{2}:\\d{2}")); + }); + expectFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got <11:22>", ^{ + expect(@"11:22").toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +- (void)testNilMatches { + expectNilFailureMessage(@"expected to match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).to(match(@"\\d{2}:\\d{2}")); + }); + expectNilFailureMessage(@"expected to not match <\\d{2}:\\d{2}>, got ", ^{ + expect(nil).toNot(match(@"\\d{2}:\\d{2}")); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..9b5a378 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m @@ -0,0 +1,178 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCRaiseExceptionTest : XCTestCase + +@end + +@implementation ObjCRaiseExceptionTest + +- (void)testPositiveMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ @throw exception; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException()); + expectAction(^{ [exception raise]; }).to(raiseException().named(NSInvalidArgumentException)); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food")); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"})); + + expectAction(^{ }).toNot(raiseException()); +} + +- (void)testPositiveMatchesWithBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); +} + +- (void)testNegativeMatches { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + + expectFailureMessage(@"expected to raise any exception, got no exception", ^{ + expectAction(^{ }).to(raiseException()); + }); + + expectFailureMessage(@"expected to raise exception with name , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(@"foo")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason , got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"cakes")); + }); + + expectFailureMessage(@"expected to raise exception with name with reason with userInfo <{k = v;}>, got no exception", ^{ + expectAction(^{ }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"k": @"v"})); + }); + + expectFailureMessage(@"expected to not raise any exception, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }", ^{ + expectAction(^{ [exception raise]; }).toNot(raiseException()); + }); +} + +- (void)testNegativeMatchesWithPassingBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + expectFailureMessage(@"expected to raise exception that satisfies block, got no exception", ^{ + expect(exception).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"LOL")); + })); + }); + + NSString *outerFailureMessage = @"expected to raise exception that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).toNot(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(@"foo"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"bar"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(NSInvalidArgumentException)); + })); + }); +} + +- (void)testNegativeMatchesWithNegativeBlocks { + __block NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException + reason:@"No food" + userInfo:@{@"key": @"value"}]; + NSString *outerFailureMessage; + + NSString *const innerFailureMessage = @"expected to equal , got "; + outerFailureMessage = @"expected to raise exception with name that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); + + + outerFailureMessage = @"expected to raise exception with name with reason with userInfo <{key = value;}> that satisfies block, got NSException { name=NSExceptionName(_rawValue: NSInvalidArgumentException), reason='No food', userInfo=[AnyHashable(\"key\"): value] }"; + expectFailureMessages((@[outerFailureMessage, innerFailureMessage]), ^{ + expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInvalidArgumentException). + reason(@"No food"). + userInfo(@{@"key": @"value"}). + satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(equal(@"foo")); + })); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m new file mode 100644 index 0000000..5b38b83 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAllOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAllOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAllOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAllOf(equal(@2), beLessThan(@3))); + expect(@2).toNot(satisfyAllOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAllOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).toNot(satisfyAllOf(beTrue(), beFalse())); + expect(@YES).toNot(satisfyAllOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match all of: {equal <3>}, and {equal <4>}, and {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAllOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match all of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, and {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAllOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAllOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAllOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m @@ -0,0 +1,32 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSatisfyAnyOfTest : XCTestCase + +@end + +@implementation ObjCSatisfyAnyOfTest + +- (void)testPositiveMatches { + expect(@2).to(satisfyAnyOf(equal(@2), equal(@3))); + expect(@2).toNot(satisfyAnyOf(equal(@3), equal(@16))); + expect(@[@1, @2, @3]).to(satisfyAnyOf(equal(@[@1, @2, @3]), allPass(beLessThan(@4)))); + expect(@NO).to(satisfyAnyOf(beTrue(), beFalse())); + expect(@YES).to(satisfyAnyOf(beTrue(), beFalse())); +} + +- (void)testNegativeMatches { + expectFailureMessage(@"expected to match one of: {equal <3>}, or {equal <4>}, or {equal <5>}, got 2", ^{ + expect(@2).to(satisfyAnyOf(equal(@3), equal(@4), equal(@5))); + }); + + expectFailureMessage(@"expected to match one of: {all be less than <4>, but failed first at element" + " <5> in <[5, 6, 7]>}, or {equal <(1, 2, 3, 4)>}, got (5,6,7)", ^{ + expect(@[@5, @6, @7]).to(satisfyAnyOf(allPass(beLessThan(@4)), equal(@[@1, @2, @3, @4]))); + }); + + expectFailureMessage(@"satisfyAnyOf must be called with at least one matcher", ^{ + expect(@"turtles").to(satisfyAnyOf()); + }); +} +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m @@ -0,0 +1,21 @@ +#import +#import +#import "NimbleSpecHelper.h" + +@interface ObjCSyncTest : XCTestCase + +@end + +@implementation ObjCSyncTest + +- (void)testFailureExpectation { + expectFailureMessage(@"fail() always fails", ^{ + fail(); + }); + + expectFailureMessage(@"This always fails", ^{ + failWithMessage(@"This always fails"); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m @@ -0,0 +1,52 @@ +#import +#import "NimbleSpecHelper.h" + +@interface ObjCUserDescriptionTest : XCTestCase + +@end + +@implementation ObjCUserDescriptionTest + +- (void)testToWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to equal <2>, got <1>", ^{ + expect(@1).toWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).toNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testNotToWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to not equal <1>, got <1>", ^{ + expect(@1).notToWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToEventuallyWithDescription { + expectFailureMessage(@"These are equal!\n" + "expected to eventually equal <2>, got <1>", ^{ + expect(@1).toEventuallyWithDescription(equal(@2), @"These are equal!"); + }); +} + +- (void)testToEventuallyNotWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toEventuallyNotWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +- (void)testToNotEventuallyWithDescription { + expectFailureMessage(@"These aren't equal!\n" + "expected to eventually not equal <1>, got <1>", ^{ + expect(@1).toNotEventuallyWithDescription(equal(@1), @"These aren't equal!"); + }); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m @@ -0,0 +1,31 @@ +@import XCTest; +@import Nimble; + +@interface ObjcStringersTest : XCTestCase + +@end + +@implementation ObjcStringersTest + +- (void)testItCanStringifyArrays { + NSArray *array = @[@1, @2, @3]; + NSString *result = NMBStringify(array); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItCanStringifyIndexSets { + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]; + NSString *result = NMBStringify(indexSet); + + expect(result).to(equal(@"(1, 2, 3)")); +} + +- (void)testItRoundsLongDecimals { + NSNumber *num = @291.123782163; + NSString *result = NMBStringify(num); + + expect(result).to(equal(@"291.1238")); +} + +@end diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/script/release b/Carthage/Checkouts/Quick/Externals/Nimble/script/release new file mode 100755 index 0000000..f61c0dc --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/script/release @@ -0,0 +1,187 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Nimble +PODSPEC=Nimble.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=/tmp/nimble.release.notes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "---------------- Released as $VERSION_TAG ----------------" +echo + +echo +echo "Pushing to pod trunk..." + +# NOTE: remove allow-warnings after v9.0.0 of Nimble +$POD trunk push "$PODSPEC" --allow-warnings + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for GitHub styling." +echo " - Announce!" + +open "https://github.com/Quick/Nimble/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Quick/Externals/Nimble/test b/Carthage/Checkouts/Quick/Externals/Nimble/test new file mode 100755 index 0000000..0766351 --- /dev/null +++ b/Carthage/Checkouts/Quick/Externals/Nimble/test @@ -0,0 +1,156 @@ +#!/bin/bash + +GREEN="\033[0;32m" +CLEAR="\033[0m" + +if which xcodebuild > /dev/null; then + echo -e "Gathering ${GREEN}xcodebuild sdk versions${CLEAR}..." + BUILD_DIR=`pwd`/build + LATEST_IOS_SDK_VERSION=`xcodebuild -showsdks | grep iphonesimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_TVOS_SDK_VERSION=`xcodebuild -showsdks | grep appletvsimulator | cut -d ' ' -f 4 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + LATEST_MACOS_SDK_VERSION=`xcodebuild -showsdks | grep 'macosx' | cut -d ' ' -f 3 | ruby -e 'puts STDIN.read.chomp.split("\n").last'` + BUILD_IOS_SDK_VERSION=${NIMBLE_BUILD_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + RUNTIME_IOS_SDK_VERSION=${NIMBLE_RUNTIME_IOS_SDK_VERSION:-$LATEST_IOS_SDK_VERSION} + BUILD_TVOS_SDK_VERSION=${NIMBLE_BUILD_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + RUNTIME_TVOS_SDK_VERSION=${NIMBLE_RUNTIME_TVOS_SDK_VERSION:-$LATEST_TVOS_SDK_VERSION} + BUILD_MACOS_SDK_VERSION=${NIMBLE_BUILD_MACOS_SDK_VERSION:-$LATEST_MACOS_SDK_VERSION} +fi + +set -e + +function color_if_overridden { + local actual=$1 + local env_var=$2 + if [ -z "$env_var" ]; then + printf "$actual" + else + printf "$GREEN$actual$CLEAR" + fi +} + +function print_env { + echo "=== Environment ===" + echo " iOS:" + echo " Latest iOS SDK: $LATEST_IOS_SDK_VERSION" + echo " Building with iOS SDK: `color_if_overridden $BUILD_IOS_SDK_VERSION $NIMBLE_BUILD_IOS_SDK_VERSION`" + echo " Running with iOS SDK: `color_if_overridden $RUNTIME_IOS_SDK_VERSION $NIMBLE_RUNTIME_IOS_SDK_VERSION`" + echo + echo " tvOS:" + echo " Latest tvOS SDK: $LATEST_TVOS_SDK_VERSION" + echo " Building with tvOS SDK: `color_if_overridden $BUILD_TVOS_SDK_VERSION $NIMBLE_BUILD_TVOS_SDK_VERSION`" + echo " Running with tvOS SDK: `color_if_overridden $RUNTIME_TVOS_SDK_VERSION $NIMBLE_RUNTIME_TVOS_SDK_VERSION`" + echo + echo " macOS:" + echo " Latest macOS SDK: $LATEST_MACOS_SDK_VERSION" + echo " Building with macOS SDK: `color_if_overridden $BUILD_MACOS_SDK_VERSION $NIMBLE_BUILD_MACOS_SDK_VERSION`" + echo + echo "======= END =======" + echo +} + +function run { + echo -e "$GREEN==>$CLEAR $@" + "$@" +} + +function test_ios { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPad Air,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building + + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-iOS" -configuration "Debug" -sdk "iphonesimulator$BUILD_IOS_SDK_VERSION" -destination "name=iPhone 5s,OS=$RUNTIME_IOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_tvos { + run osascript -e 'tell app "Simulator" to quit' + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-tvOS" -configuration "Debug" -sdk "appletvsimulator$BUILD_TVOS_SDK_VERSION" -destination "name=Apple TV 1080p,OS=$RUNTIME_TVOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_macos { + run xcodebuild -project Nimble.xcodeproj -scheme "Nimble-macOS" -configuration "Debug" -sdk "macosx$BUILD_MACOS_SDK_VERSION" build-for-testing test-without-building +} + +function test_podspec { + echo "Gathering CocoaPods installation information..." + run bundle exec pod --version + echo "Linting podspec..." + # Note: remove `--allow-warnings` once old Matcher API has been removed + run bundle exec pod lib lint Nimble.podspec --allow-warnings +} + +function test_swiftpm { + if [ -d .build ]; then + run swift build --clean + fi + run swift build && swift test +} + +function test_swiftpm_docker { + run docker build -t nimble-tests -f Dockerfile.test --no-cache . + run docker run -it --privileged=true nimble-tests +} + +function test() { + test_ios + test_tvos + test_macos + + if which swift-test; then + test_swiftpm + else + echo "Not testing with the Swift Package Manager because swift-test is not installed" + fi + + if which docker; then + test_swiftpm_docker + else + echo "Not testing linux in docker container since docker is not in PATH!" + fi +} + +function clean { + run rm -rf ~/Library/Developer/Xcode/DerivedData\; true +} + +function help { + echo "Usage: $0 COMMANDS" + echo + echo "COMMANDS:" + echo " all - Runs the all tests of macos, ios and tvos" + echo " clean - Cleans the derived data directory of Xcode. Assumes default location" + echo " help - Displays this help" + echo " ios - Runs the tests as an iOS device" + echo " macos - Runs the tests on macOS 10.10 (Yosemite and newer only)" + echo " podspec - Runs pod lib lint against the podspec to detect breaking changes" + echo " swiftpm - Runs the tests built by the Swift Package Manager" + echo " swiftpm_docker - Runs the tests built by the Swift Package Manager in a docker linux container" + echo " tvos - Runs the tests as an tvOS device" + echo + exit 1 +} + +function main { + print_env + for arg in $@ + do + case "$arg" in + clean) clean ;; + ios) test_ios ;; + tvos) test_tvos ;; + macos) test_macos ;; + podspec) test_podspec ;; + test) test ;; + all) test ;; + swiftpm) test_swiftpm ;; + swiftpm_docker) test_swiftpm_docker ;; + help) help ;; + esac + done + + if [ $# -eq 0 ]; then + clean + test + fi +} + +main $@ diff --git a/Carthage/Checkouts/Quick/Gemfile b/Carthage/Checkouts/Quick/Gemfile new file mode 100644 index 0000000..716d667 --- /dev/null +++ b/Carthage/Checkouts/Quick/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem 'cocoapods', '~> 1.5.0' +gem 'danger' +gem 'danger-swiftlint' diff --git a/Carthage/Checkouts/Quick/Gemfile.lock b/Carthage/Checkouts/Quick/Gemfile.lock new file mode 100644 index 0000000..9a0bf21 --- /dev/null +++ b/Carthage/Checkouts/Quick/Gemfile.lock @@ -0,0 +1,117 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) + atomos (0.1.2) + claide (1.0.2) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + cocoapods (1.5.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.5.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) + cocoapods-downloader (>= 1.2.0, < 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.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.6.5) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.7, < 2.0) + cocoapods-core (1.5.0) + activesupport (>= 4.0.2, < 6) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.2) + cocoapods-downloader (1.2.0) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.3.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.1.0) + colored (1.2) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + cork (0.2.0) + colored (~> 1.2) + danger (4.0.4) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored (~> 1.2) + cork (~> 0.1) + faraday (~> 0.9) + faraday-http-cache (~> 1.0) + git (~> 1) + kramdown (~> 1.5) + octokit (~> 4.2) + terminal-table (~> 1) + danger-swiftlint (0.2.1) + danger + escape (0.0.4) + faraday (0.10.1) + multipart-post (>= 1.2, < 3) + faraday-http-cache (1.3.1) + faraday (~> 0.8) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + git (1.3.0) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + kramdown (1.13.2) + minitest (5.11.3) + molinillo (0.6.5) + multipart-post (2.0.0) + nanaimo (0.2.5) + nap (1.1.0) + netrc (0.11.0) + octokit (4.6.2) + sawyer (~> 0.8.0, >= 0.5.3) + open4 (1.3.4) + public_suffix (2.0.5) + ruby-macho (1.1.0) + sawyer (0.8.1) + addressable (>= 2.3.5, < 2.6) + faraday (~> 0.8, < 1.0) + terminal-table (1.7.3) + unicode-display_width (~> 1.1.1) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + unicode-display_width (1.1.2) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 1.5.0) + danger + danger-swiftlint + +BUNDLED WITH + 1.16.1 diff --git a/Carthage/Checkouts/Quick/LICENSE b/Carthage/Checkouts/Quick/LICENSE new file mode 100644 index 0000000..e900165 --- /dev/null +++ b/Carthage/Checkouts/Quick/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014, Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Carthage/Checkouts/Quick/Package.resolved b/Carthage/Checkouts/Quick/Package.resolved new file mode 100644 index 0000000..4651c1a --- /dev/null +++ b/Carthage/Checkouts/Quick/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Nimble", + "repositoryURL": "https://github.com/Quick/Nimble.git", + "state": { + "branch": null, + "revision": "9c1379fdcd58c4f2278aea5e029394ba9a2b8f07", + "version": "7.1.3" + } + } + ] + }, + "version": 1 +} diff --git a/Carthage/Checkouts/Quick/Package.swift b/Carthage/Checkouts/Quick/Package.swift new file mode 100644 index 0000000..07b93b4 --- /dev/null +++ b/Carthage/Checkouts/Quick/Package.swift @@ -0,0 +1,47 @@ +// swift-tools-version:3.1 + +import Foundation +import PackageDescription + +var isTesting: Bool { + guard let value = ProcessInfo.processInfo.environment["SWIFT_PACKAGE_TEST_Quick"] else { return false } + return NSString(string: value).boolValue +} + +var package = Package( + name: "Quick", + targets: { +#if os(macOS) + return [ + Target(name: "QuickSpecBase"), + Target(name: "Quick", dependencies: [ "QuickSpecBase" ]), + Target(name: "QuickTests", dependencies: [ "Quick" ]), + ] +#else + return [ + Target(name: "Quick"), + Target(name: "QuickTests", dependencies: [ "Quick" ]), + ] +#endif + }(), + exclude: { + var excludes = [ + "Sources/QuickObjectiveC", + "Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m", + "Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m", + "Tests/QuickTests/QuickTests/FunctionalTests/ObjC", + "Tests/QuickTests/QuickTests/Helpers", + "Tests/QuickTests/QuickTests/QuickConfigurationTests.m", + ] +#if !os(macOS) + excludes.append("Sources/QuickSpecBase") +#endif + return excludes + }() +) + +if isTesting { + package.dependencies.append(contentsOf: [ + .Package(url: "https://github.com/Quick/Nimble.git", majorVersion: 7), + ]) +} diff --git a/Carthage/Checkouts/Quick/Package@swift-4.swift b/Carthage/Checkouts/Quick/Package@swift-4.swift new file mode 100644 index 0000000..7f230fd --- /dev/null +++ b/Carthage/Checkouts/Quick/Package@swift-4.swift @@ -0,0 +1,40 @@ +// swift-tools-version:4.0 + +import PackageDescription + +let package = Package( + name: "Quick", + products: [ + .library(name: "Quick", targets: ["Quick"]), + ], + dependencies: [ + .package(url: "https://github.com/Quick/Nimble.git", from: "7.0.1"), + ], + targets: { + var targets: [Target] = [ + .testTarget( + name: "QuickTests", + dependencies: [ "Quick", "Nimble" ], + exclude: [ + "QuickAfterSuiteTests/AfterSuiteTests+ObjC.m", + "QuickFocusedTests/FocusedTests+ObjC.m", + "QuickTests/FunctionalTests/ObjC", + "QuickTests/Helpers", + "QuickTests/QuickConfigurationTests.m", + ] + ), + ] +#if os(macOS) + targets.append(contentsOf: [ + .target(name: "QuickSpecBase", dependencies: []), + .target(name: "Quick", dependencies: [ "QuickSpecBase" ]), + ]) +#else + targets.append(contentsOf: [ + .target(name: "Quick", dependencies: []), + ]) +#endif + return targets + }(), + swiftLanguageVersions: [3] +) diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h new file mode 100644 index 0000000..b934bcb --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h @@ -0,0 +1,13 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +@import Quick; + +@interface ___FILEBASENAMEASIDENTIFIER___ : QuickConfiguration + +@end diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m new file mode 100644 index 0000000..cd3f486 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m @@ -0,0 +1,17 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +#import "___FILEBASENAMEASIDENTIFIER___.h" + +@implementation ___FILEBASENAMEASIDENTIFIER___ + ++ (void)configure:(Configuration *)configuration { + +} + +@end diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..ae0acbb --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift @@ -0,0 +1,15 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +import Quick + +class ___FILEBASENAMEASIDENTIFIER___: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + + } +} diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000..5cb4ae9 Binary files /dev/null and b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns differ diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..146a6df --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist @@ -0,0 +1,73 @@ + + + + + Kind + Xcode.IDEKit.TextSubstitutionFileTemplateKind + Description + A QuickConfiguration subclass. + Summary + A QuickConfiguration subclass, overload +configure: to configure the behaviour when running specs, shared examples that are used across spec files. + SortOrder + 1 + BuildableType + Test + DefaultCompletionName + Spec + Options + + + Description + Name of the Quick Configuration + Identifier + productName + Name + QuickConfiguration Name: + NotPersisted + + Required + + Type + text + + + AllowedTypes + + Swift + + public.swift-source + + Objective-C + + public.objective-c-source + public.objective-c-plus-plus-source + + + Default + Swift + Description + The implementation language + Identifier + languageChoice + MainTemplateFiles + + Objective-C + ___FILEBASENAME___.m + Swift + ___FILEBASENAME___.swift + + Name + Language: + Required + Yes + Type + popup + Values + + Swift + Objective-C + + + + + diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m new file mode 100644 index 0000000..3e8da5b --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m @@ -0,0 +1,14 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +#import +#import + +QuickSpecBegin(___FILEBASENAMEASIDENTIFIER___) + +QuickSpecEnd diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..a8371cf --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift @@ -0,0 +1,16 @@ +// +// ___FILENAME___ +// ___PROJECTNAME___ +// +// Created by ___FULLUSERNAME___ on ___DATE___. +//___COPYRIGHT___ +// + +import Quick +import Nimble + +class ___FILEBASENAMEASIDENTIFIER___: QuickSpec { + override func spec() { + + } +} diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000..5cb4ae9 Binary files /dev/null and b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns differ diff --git a/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..7b8088f --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist @@ -0,0 +1,73 @@ + + + + + Kind + Xcode.IDEKit.TextSubstitutionFileTemplateKind + Description + A class implementing a Quick spec. + Summary + A class implementing a Quick spec + SortOrder + 1 + BuildableType + Test + DefaultCompletionName + Spec + Options + + + Description + Name of the Quick spec class + Identifier + productName + Name + Spec Name: + NotPersisted + + Required + + Type + text + + + AllowedTypes + + Swift + + public.swift-source + + Objective-C + + public.objective-c-source + public.objective-c-plus-plus-source + + + Default + Swift + Description + The implementation language + Identifier + languageChoice + MainTemplateFiles + + Objective-C + ___FILEBASENAME___.m + Swift + ___FILEBASENAME___.swift + + Name + Language: + Required + Yes + Type + popup + Values + + Swift + Objective-C + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.podspec b/Carthage/Checkouts/Quick/Quick.podspec new file mode 100644 index 0000000..d234718 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.podspec @@ -0,0 +1,42 @@ +Pod::Spec.new do |s| + s.name = "Quick" + s.version = "1.3.1" + s.summary = "The Swift (and Objective-C) testing framework." + + s.description = <<-DESC + Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo. + DESC + + s.homepage = "https://github.com/Quick/Quick" + s.license = { :type => "Apache 2.0", :file => "LICENSE" } + + s.author = "Quick Contributors" + s.ios.deployment_target = "7.0" + s.osx.deployment_target = "10.9" + s.tvos.deployment_target = '9.0' + + s.source = { :git => "https://github.com/Quick/Quick.git", :tag => "v#{s.version}" } + s.source_files = "Sources/**/*.{swift,h,m}" + + s.public_header_files = [ + 'Sources/QuickObjectiveC/Configuration/QuickConfiguration.h', + 'Sources/QuickObjectiveC/DSL/QCKDSL.h', + 'Sources/QuickObjectiveC/Quick.h', + 'Sources/QuickObjectiveC/QuickSpec.h', + ] + + s.exclude_files = [ + 'Sources/Quick/Configuration/QuickConfiguration.swift', + 'Sources/Quick/QuickSpec.swift', + 'Sources/Quick/QuickMain.swift', + ] + + s.framework = "XCTest" + s.requires_arc = true + s.user_target_xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '$(PLATFORM_DIR)/Developer/Library/Frameworks' } + s.pod_target_xcconfig = { + 'APPLICATION_EXTENSION_API_ONLY' => 'YES', + 'ENABLE_BITCODE' => 'NO', + 'OTHER_LDFLAGS' => '$(inherited) -Xlinker -no_application_extension', + } +end diff --git a/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj b/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2b043ad --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj @@ -0,0 +1,2723 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 732D8D691E516780008558BD /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 732D8D6A1E516780008558BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + 732D8D6D1E516789008558BD /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1F118CDF1BDCA4AB005013A2 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 1F118CF51BDCA4BB005013A2 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 1F118CFB1BDCA536005013A2 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + 1F118CFC1BDCA536005013A2 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + 1F118CFD1BDCA536005013A2 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + 1F118CFE1BDCA536005013A2 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + 1F118CFF1BDCA536005013A2 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + 1F118D001BDCA536005013A2 /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + 1F118D011BDCA536005013A2 /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + 1F118D021BDCA536005013A2 /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + 1F118D031BDCA536005013A2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 1F118D041BDCA536005013A2 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 1F118D051BDCA536005013A2 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + 1F118D061BDCA536005013A2 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 1F118D071BDCA536005013A2 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 1F118D081BDCA536005013A2 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + 1F118D091BDCA536005013A2 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 1F118D0C1BDCA543005013A2 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + 1F118D0D1BDCA547005013A2 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + 1F118D0E1BDCA547005013A2 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + 1F118D0F1BDCA54B005013A2 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + 1F118D101BDCA556005013A2 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + 1F118D111BDCA556005013A2 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + 1F118D121BDCA556005013A2 /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + 1F118D131BDCA556005013A2 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 1F118D141BDCA556005013A2 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + 1F118D151BDCA556005013A2 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + 1F118D161BDCA556005013A2 /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + 1F118D171BDCA556005013A2 /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 1F118D181BDCA556005013A2 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + 1F118D191BDCA556005013A2 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 1F118D1A1BDCA556005013A2 /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + 1F118D1B1BDCA556005013A2 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 1F118D1C1BDCA556005013A2 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + 1F118D1D1BDCA556005013A2 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 1F118D201BDCA556005013A2 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + 1F118D211BDCA556005013A2 /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 1F118D221BDCA556005013A2 /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + 1F118D231BDCA556005013A2 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 1F118D241BDCA561005013A2 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + 1F118D251BDCA561005013A2 /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + 1F118D291BDCA5B6005013A2 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2A1BDCA5B6005013A2 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2B1BDCA5B6005013A2 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D2C1BDCA5B6005013A2 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F118D351BDCA657005013A2 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D341BDCA657005013A2 /* Nimble.framework */; }; + 1F118D371BDCA65C005013A2 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D361BDCA65C005013A2 /* Nimble.framework */; }; + 1F118D381BDCA6E1005013A2 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + 1F118D391BDCA6E6005013A2 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + 1FD0CFAD1AFA0B8C00874CC1 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 34C586011C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586021C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586031C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586041C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586051C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586061C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */; }; + 34C586081C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34C586091C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34C5860A1C4AC5E500D4F057 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */; }; + 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759C19515CA700CE1B99 /* Callsite.swift */; }; + 34F375AB19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 34F375AC19515CA700CE1B99 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759E19515CA700CE1B99 /* Example.swift */; }; + 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */; }; + 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F375A419515CA700CE1B99 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A519515CA700CE1B99 /* QuickSpec.m */; }; + 34F375BB19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 34F375BC19515CA700CE1B99 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F375A619515CA700CE1B99 /* World.swift */; }; + 470D6ECB1A43442400043E50 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 470D6ECC1A43442900043E50 /* AfterEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */; }; + 471590401A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 471590411A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */; }; + 4728253B1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 4728253C1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */; }; + 4748E8941A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 4748E8951A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */; }; + 47876F7D1A49AD63002575C7 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 47876F7E1A49AD71002575C7 /* BeforeSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */; }; + 479C31E31A36171B00DA8718 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 479C31E41A36172700DA8718 /* ItTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */; }; + 47FAEA361A3F49E6005A1D2F /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 47FAEA371A3F49EB005A1D2F /* BeforeEachTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */; }; + 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + 5A5D11A7194740E000F6D13D /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 64076CEF1D6D7C2000E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + 64076CF01D6D7C2000E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 64076D021D6D7CD600E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + 64076D031D6D7CD600E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + 64076D141D6D7CEA00E2B499 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; }; + 64076D151D6D7CEA00E2B499 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F118D361BDCA65C005013A2 /* Nimble.framework */; }; + 64076D211D6D7E4D00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D221D6D7E5B00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D231D6D7E6B00E2B499 /* AfterSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */; }; + 64076D261D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + 64076D271D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + 7B44ADBE1C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B44ADBF1C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B44ADC01C5444940007AF2E /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */; }; + 7B5358CE1C3D4FBC00A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 7B5358CF1C3D4FBE00A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 7B5358D01C3D4FC000A23FAA /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */; }; + 8D010A571C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + 8D010A581C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + 8D010A591C11726F00633E2B /* DescribeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D010A561C11726F00633E2B /* DescribeTests.swift */; }; + AE4E58131C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58141C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58151C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58161C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58171C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AE4E58181C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */; }; + AED9C8631CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + AED9C8641CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + AED9C8651CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */; }; + CD264DBD1DDA147A0038B0EB /* AfterSuiteTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */; }; + CD564DA020B5B09C00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + CD564DA120B5B09D00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + CD564DA220B5B09E00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */; }; + CE175D4E1E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE175D4F1E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE175D501E8D6B4900EB5E84 /* Behavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */; }; + CE4A578A1EA5DC270063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE4A578E1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57911EA7252E0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57921EA725300063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */; }; + CE4A57931EA725420063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE4A57941EA725440063C0D4 /* BehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */; }; + CE57CEDD1C430BD200D63004 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE57CEDE1C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE57CEDF1C430BD200D63004 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE57CEE01C430BD200D63004 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE57CEE11C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + CE590E1A1C431FE300253D19 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE590E1B1C431FE300253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE590E1C1C431FE300253D19 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE590E1D1C431FE300253D19 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE590E1E1C431FE300253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + CE590E1F1C431FE400253D19 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */; }; + CE590E201C431FE400253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */; }; + CE590E211C431FE400253D19 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */; }; + CE590E221C431FE400253D19 /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDB1C430BD200D63004 /* URL+FileName.swift */; }; + CE590E231C431FE400253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA02C91819A8073100093156 /* ExampleMetadata.swift */; }; + DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA05D60F19F73A3800771050 /* AfterEachTests.swift */; }; + DA07722E1A4E5B7B0098839D /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA07722F1A4E5B7C0098839D /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA169E4819FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + DA169E4919FF5DF100619816 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA169E4719FF5DF100619816 /* Configuration.swift */; }; + DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E219FCAEE8002858A7 /* DSL.swift */; }; + DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3124E319FCAEE8002858A7 /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E419FCAEE8002858A7 /* QCKDSL.m */; }; + DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA3124E519FCAEE8002858A7 /* World+DSL.swift */; }; + DA3E7A341A1E66C600CCE408 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DA3E7A351A1E66CB00CCE408 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DA408BE219FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + DA408BE319FF5599005DF92A /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BDF19FF5599005DF92A /* Closures.swift */; }; + DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE019FF5599005DF92A /* ExampleHooks.swift */; }; + DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA408BE119FF5599005DF92A /* SuiteHooks.swift */; }; + DA5663EE1A4C8D8500193C88 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + DA5663F41A4C8D9A00193C88 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + DA5CBB491EAFA61A00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA5CBB4A1EAFA61C00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA5CBB4B1EAFA61D00297C9E /* CurrentSpecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */; }; + DA6B30181A4DB0D500FFB148 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + DA6B30191A4DB0D500FFB148 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6B30171A4DB0D500FFB148 /* Filter.swift */; }; + DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA7AE6F019FC493F000AFDCE /* ItTests.swift */; }; + DA8940F01B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + DA8940F11B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */; }; + DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */; }; + DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919619F31680006F6675 /* QCKSpecRunner.m */; }; + DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */; }; + DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */; }; + DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */; }; + DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */; }; + DA9876B81A4C70EB0004AA17 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A5D117C19473F2100F6D13D /* Quick.framework */; }; + DA9876C11A4C87200004AA17 /* FocusedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9876BF1A4C87200004AA17 /* FocusedTests.swift */; }; + DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA63EA219F7637300CD0A3B /* PendingTests.swift */; }; + DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */; }; + DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA87078219F48775008C04AC /* BeforeEachTests.swift */; }; + DAD297651AA8129D001D25CD /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8100E901A1E4447007595ED /* Nimble.framework */; }; + DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */; }; + DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */; }; + DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */; }; + DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */; }; + DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */; }; + DAEB6B941943873100289F44 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB6B931943873100289F44 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEB6B8E1943873100289F44 /* Quick.framework */; }; + DAF28BC31A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + DAF28BC41A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */; }; + DED3036B1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3036C1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3036D1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */; }; + DED3037D1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; + DED3037E1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; + DED3037F1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 047655511949F4CB00B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 047655531949F4CB00B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04765555194A327000B288BB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + 1F118CE01BDCA4AB005013A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 1F118CF61BDCA4BB005013A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 64076CE71D6D7C2000E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = "Quick-OSX"; + }; + 64076CFA1D6D7CD600E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + 64076D0C1D6D7CEA00E2B499 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1F118CD41BDCA4AB005013A2; + remoteInfo = "Quick-tvOS"; + }; + 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; + DA5663EF1A4C8D8500193C88 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = "Quick-OSX"; + }; + DA9876B91A4C70EB0004AA17 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A5D117B19473F2100F6D13D; + remoteInfo = "Quick-iOS"; + }; + DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DAEB6B851943873100289F44 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DAEB6B8D1943873100289F44; + remoteInfo = Quick; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1F118CD51BDCA4AB005013A2 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F118D341BDCA657005013A2 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = "Externals/Nimble/build/Debug-appletvos/Nimble.framework"; sourceTree = ""; }; + 1F118D361BDCA65C005013A2 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = "Externals/Nimble/build/Debug-appletvos/Nimble.framework"; sourceTree = ""; }; + 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = XCTestCaseProvider.swift; path = ../../QuickTestHelpers/XCTestCaseProvider.swift; sourceTree = ""; }; + 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorUtility.swift; sourceTree = ""; }; + 34F3759C19515CA700CE1B99 /* Callsite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Callsite.swift; sourceTree = ""; }; + 34F3759E19515CA700CE1B99 /* Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = ""; }; + 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleGroup.swift; sourceTree = ""; }; + 34F375A419515CA700CE1B99 /* QuickSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickSpec.h; sourceTree = ""; }; + 34F375A519515CA700CE1B99 /* QuickSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickSpec.m; sourceTree = ""; }; + 34F375A619515CA700CE1B99 /* World.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; + 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AfterEachTests+ObjC.m"; sourceTree = ""; }; + 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PendingTests+ObjC.m"; sourceTree = ""; }; + 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SharedExamplesTests+ObjC.m"; sourceTree = ""; }; + 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SharedExamples+BeforeEachTests+ObjC.m"; sourceTree = ""; }; + 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BeforeSuiteTests+ObjC.m"; sourceTree = ""; }; + 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ItTests+ObjC.m"; sourceTree = ""; }; + 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BeforeEachTests+ObjC.m"; sourceTree = ""; }; + 5A5D117C19473F2100F6D13D /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickAfterSuite - tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterSuiteTests.swift; sourceTree = ""; }; + 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AfterSuiteTests+ObjC.m"; sourceTree = ""; }; + 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HooksPhase.swift; sourceTree = ""; }; + 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextTests.swift; sourceTree = ""; }; + 8D010A561C11726F00633E2B /* DescribeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DescribeTests.swift; sourceTree = ""; }; + 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "QuickSpec+QuickSpec_MethodList.h"; sourceTree = ""; }; + 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "QuickSpec+QuickSpec_MethodList.m"; sourceTree = ""; }; + AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestObservationCenter+QCKSuspendObservation.m"; sourceTree = ""; }; + AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossReferencingSpecs.swift; sourceTree = ""; }; + CD261AC81DEC8B0000A8863C /* QuickConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickConfiguration.swift; sourceTree = ""; }; + CD3451461E4703D4000C8633 /* QuickMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickMain.swift; sourceTree = ""; }; + CD3451471E4703D4000C8633 /* QuickSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickSpec.swift; sourceTree = ""; }; + CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Behavior.swift; sourceTree = ""; }; + CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BehaviorTests.swift; sourceTree = ""; }; + CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests_BehaviorTests_Behaviors.swift; sourceTree = ""; }; + CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSBundle+CurrentTestBundle.swift"; sourceTree = ""; }; + CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickSelectedTestSuiteBuilder.swift; sourceTree = ""; }; + CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickTestSuite.swift; sourceTree = ""; }; + CE57CEDB1C430BD200D63004 /* URL+FileName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+FileName.swift"; sourceTree = ""; }; + CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestSuite+QuickTestSuiteBuilder.m"; sourceTree = ""; }; + DA02C91819A8073100093156 /* ExampleMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleMetadata.swift; sourceTree = ""; }; + DA05D60F19F73A3800771050 /* AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterEachTests.swift; sourceTree = ""; }; + DA169E4719FF5DF100619816 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; + DA3124E219FCAEE8002858A7 /* DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DSL.swift; sourceTree = ""; }; + DA3124E319FCAEE8002858A7 /* QCKDSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKDSL.h; sourceTree = ""; }; + DA3124E419FCAEE8002858A7 /* QCKDSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKDSL.m; sourceTree = ""; }; + DA3124E519FCAEE8002858A7 /* World+DSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "World+DSL.swift"; sourceTree = ""; }; + DA408BDF19FF5599005DF92A /* Closures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Closures.swift; sourceTree = ""; }; + DA408BE019FF5599005DF92A /* ExampleHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleHooks.swift; sourceTree = ""; }; + DA408BE119FF5599005DF92A /* SuiteHooks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuiteHooks.swift; sourceTree = ""; }; + DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrentSpecTests.swift; sourceTree = ""; }; + DA6B30171A4DB0D500FFB148 /* Filter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; + DA7AE6F019FC493F000AFDCE /* ItTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItTests.swift; sourceTree = ""; }; + DA87078219F48775008C04AC /* BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeEachTests.swift; sourceTree = ""; }; + DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FailureUsingXCTAssertTests+ObjC.m"; sourceTree = ""; }; + DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfigurationTests.m; sourceTree = ""; }; + DA8F919519F31680006F6675 /* QCKSpecRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QCKSpecRunner.h; sourceTree = ""; }; + DA8F919619F31680006F6675 /* QCKSpecRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QCKSpecRunner.m; sourceTree = ""; }; + DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickTestsBridgingHeader.h; sourceTree = ""; }; + DA8F919819F31680006F6675 /* XCTestObservationCenter+QCKSuspendObservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCTestObservationCenter+QCKSuspendObservation.h"; sourceTree = ""; }; + DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FailureTests+ObjC.m"; sourceTree = ""; }; + DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeforeSuiteTests.swift; sourceTree = ""; }; + DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExamplesTests.swift; sourceTree = ""; }; + DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalTests_SharedExamplesTests_SharedExamples.swift; sourceTree = ""; }; + DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "QuickFocused - iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DA9876BF1A4C87200004AA17 /* FocusedTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FocusedTests.swift; sourceTree = ""; }; + DA9876C01A4C87200004AA17 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAA63EA219F7637300CD0A3B /* PendingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingTests.swift; sourceTree = ""; }; + DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SharedExamples+BeforeEachTests.swift"; sourceTree = ""; }; + DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEachTests.swift"; sourceTree = ""; }; + DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+BeforeEach.swift"; sourceTree = ""; }; + DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEach.swift"; sourceTree = ""; }; + DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+AfterEachTests.swift"; sourceTree = ""; }; + DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickConfiguration.h; sourceTree = ""; }; + DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuickConfiguration.m; sourceTree = ""; }; + DAEB6B8E1943873100289F44 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DAEB6B921943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAEB6B931943873100289F44 /* Quick.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Quick.h; sourceTree = ""; }; + DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Quick - macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DAEB6B9F1943873100289F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FocusedTests+ObjC.m"; sourceTree = ""; }; + DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSString+C99ExtendedIdentifier.swift"; sourceTree = ""; }; + DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleModuleNameTests.swift; sourceTree = ""; }; + F8100E901A1E4447007595ED /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F118CD11BDCA4AB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDB1BDCA4AB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118CDF1BDCA4AB005013A2 /* Quick.framework in Frameworks */, + 1F118D351BDCA657005013A2 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CED1BDCA4BB005013A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118CF51BDCA4BB005013A2 /* Quick.framework in Frameworks */, + 1F118D371BDCA65C005013A2 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117819473F2100F6D13D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118319473F2100F6D13D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5A5D118719473F2100F6D13D /* Quick.framework in Frameworks */, + DA3E7A351A1E66CB00CCE408 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CEE1D6D7C2000E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076CEF1D6D7C2000E2B499 /* Quick.framework in Frameworks */, + 64076CF01D6D7C2000E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D011D6D7CD600E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D021D6D7CD600E2B499 /* Quick.framework in Frameworks */, + 64076D031D6D7CD600E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D131D6D7CEA00E2B499 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D141D6D7CEA00E2B499 /* Quick.framework in Frameworks */, + 64076D151D6D7CEA00E2B499 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E51A4C8D8500193C88 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA5663EE1A4C8D8500193C88 /* Quick.framework in Frameworks */, + 1FD0CFAD1AFA0B8C00874CC1 /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876AF1A4C70EB0004AA17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA9876B81A4C70EB0004AA17 /* Quick.framework in Frameworks */, + DAD297651AA8129D001D25CD /* Nimble.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8A1943873100289F44 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B961943873100289F44 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DA3E7A341A1E66C600CCE408 /* Nimble.framework in Frameworks */, + DAEB6B9A1943873100289F44 /* Quick.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F118D331BDCA645005013A2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1F118D361BDCA65C005013A2 /* Nimble.framework */, + 1F118D341BDCA657005013A2 /* Nimble.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 64076D1C1D6D7D0B00E2B499 /* QuickAfterSuiteTests */ = { + isa = PBXGroup; + children = ( + 64076D1D1D6D7D0B00E2B499 /* AfterSuiteTests.swift */, + 64076D241D6D80B500E2B499 /* AfterSuiteTests+ObjC.m */, + ); + name = QuickAfterSuiteTests; + path = Tests/QuickTests/QuickAfterSuiteTests; + sourceTree = ""; + }; + 6C3983EE1D1E930D00637469 /* QuickObjectiveC */ = { + isa = PBXGroup; + children = ( + 6C3983EF1D1E93B700637469 /* Configuration */, + 6C3983F01D1E93CE00637469 /* DSL */, + DAEB6B931943873100289F44 /* Quick.h */, + 34F375A419515CA700CE1B99 /* QuickSpec.h */, + 34F375A519515CA700CE1B99 /* QuickSpec.m */, + CE57CEDC1C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m */, + ); + name = QuickObjectiveC; + path = Sources/QuickObjectiveC; + sourceTree = ""; + }; + 6C3983EF1D1E93B700637469 /* Configuration */ = { + isa = PBXGroup; + children = ( + DAE714FC19FF6A62005905B8 /* QuickConfiguration.h */, + DAE714FD19FF6A62005905B8 /* QuickConfiguration.m */, + ); + path = Configuration; + sourceTree = ""; + }; + 6C3983F01D1E93CE00637469 /* DSL */ = { + isa = PBXGroup; + children = ( + DA3124E319FCAEE8002858A7 /* QCKDSL.h */, + DA3124E419FCAEE8002858A7 /* QCKDSL.m */, + ); + path = DSL; + sourceTree = ""; + }; + CDB2AA5E1D6C84CF005600C3 /* ObjC */ = { + isa = PBXGroup; + children = ( + 470D6EC91A43409600043E50 /* AfterEachTests+ObjC.m */, + 47FAEA341A3F45ED005A1D2F /* BeforeEachTests+ObjC.m */, + 47876F7B1A4999B0002575C7 /* BeforeSuiteTests+ObjC.m */, + DA8F919C19F31921006F6675 /* FailureTests+ObjC.m */, + DA8940EF1B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m */, + 479C31E11A36156E00DA8718 /* ItTests+ObjC.m */, + 4715903F1A488F3F00FBA644 /* PendingTests+ObjC.m */, + 4748E8931A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m */, + 4728253A1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m */, + ); + path = ObjC; + sourceTree = ""; + }; + DA169E4619FF5DF100619816 /* Configuration */ = { + isa = PBXGroup; + children = ( + DA169E4719FF5DF100619816 /* Configuration.swift */, + CD261AC81DEC8B0000A8863C /* QuickConfiguration.swift */, + ); + path = Configuration; + sourceTree = ""; + }; + DA3124E119FCAEE8002858A7 /* DSL */ = { + isa = PBXGroup; + children = ( + DA3124E519FCAEE8002858A7 /* World+DSL.swift */, + DA3124E219FCAEE8002858A7 /* DSL.swift */, + ); + path = DSL; + sourceTree = ""; + }; + DA408BDE19FF5599005DF92A /* Hooks */ = { + isa = PBXGroup; + children = ( + DA408BDF19FF5599005DF92A /* Closures.swift */, + DA408BE019FF5599005DF92A /* ExampleHooks.swift */, + DA408BE119FF5599005DF92A /* SuiteHooks.swift */, + 7B44ADBD1C5444940007AF2E /* HooksPhase.swift */, + ); + path = Hooks; + sourceTree = ""; + }; + DA8F919419F31680006F6675 /* Helpers */ = { + isa = PBXGroup; + children = ( + DA8F919719F31680006F6675 /* QuickTestsBridgingHeader.h */, + DA8F919519F31680006F6675 /* QCKSpecRunner.h */, + DA8F919619F31680006F6675 /* QCKSpecRunner.m */, + 34ACFB7B1C34859300942064 /* XCTestCaseProvider.swift */, + DA8F919819F31680006F6675 /* XCTestObservationCenter+QCKSuspendObservation.h */, + 96327C611C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.h */, + 96327C621C56E90C00405AB3 /* QuickSpec+QuickSpec_MethodList.m */, + AEB080BB1C72F028004917D3 /* XCTestObservationCenter+QCKSuspendObservation.m */, + ); + path = Helpers; + sourceTree = ""; + }; + DA8F919B19F3189D006F6675 /* FunctionalTests */ = { + isa = PBXGroup; + children = ( + DAE714E919FF65A6005905B8 /* Configuration */, + CDB2AA5E1D6C84CF005600C3 /* ObjC */, + DA7AE6F019FC493F000AFDCE /* ItTests.swift */, + 8D010A561C11726F00633E2B /* DescribeTests.swift */, + DA87078219F48775008C04AC /* BeforeEachTests.swift */, + DA05D60F19F73A3800771050 /* AfterEachTests.swift */, + DAA63EA219F7637300CD0A3B /* PendingTests.swift */, + DA8F91A419F3208B006F6675 /* BeforeSuiteTests.swift */, + DA8F91AA19F3299E006F6675 /* SharedExamplesTests.swift */, + DAB0136E19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift */, + 7B5358CA1C3D4E2A00A23FAA /* ContextTests.swift */, + AED9C8621CC8A7BD00432F62 /* CrossReferencingSpecs.swift */, + DED3037C1DF6CF140041394E /* BundleModuleNameTests.swift */, + CE4A57891EA5DC270063C0D4 /* BehaviorTests.swift */, + DA5CBB471EAFA55800297C9E /* CurrentSpecTests.swift */, + ); + path = FunctionalTests; + sourceTree = ""; + }; + DA9876BE1A4C87200004AA17 /* QuickFocusedTests */ = { + isa = PBXGroup; + children = ( + DA9876BF1A4C87200004AA17 /* FocusedTests.swift */, + DAF28BC21A4DB8EC00A5D9BF /* FocusedTests+ObjC.m */, + DA9876C31A4C87310004AA17 /* Supporting Files */, + ); + name = QuickFocusedTests; + path = Tests/QuickTests/QuickFocusedTests; + sourceTree = ""; + }; + DA9876C31A4C87310004AA17 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DA9876C01A4C87200004AA17 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAE714E919FF65A6005905B8 /* Configuration */ = { + isa = PBXGroup; + children = ( + DAE714F519FF67FF005905B8 /* AfterEach */, + DAE714EA19FF65A6005905B8 /* BeforeEach */, + ); + path = Configuration; + sourceTree = ""; + }; + DAE714EA19FF65A6005905B8 /* BeforeEach */ = { + isa = PBXGroup; + children = ( + DAE714F219FF65E7005905B8 /* Configuration+BeforeEach.swift */, + DAE714EF19FF65D3005905B8 /* Configuration+BeforeEachTests.swift */, + ); + path = BeforeEach; + sourceTree = ""; + }; + DAE714F519FF67FF005905B8 /* AfterEach */ = { + isa = PBXGroup; + children = ( + DAE714F619FF6812005905B8 /* Configuration+AfterEach.swift */, + DAE714F919FF682A005905B8 /* Configuration+AfterEachTests.swift */, + ); + path = AfterEach; + sourceTree = ""; + }; + DAEB6B841943873100289F44 = { + isa = PBXGroup; + children = ( + DAEB6B901943873100289F44 /* Quick */, + 6C3983EE1D1E930D00637469 /* QuickObjectiveC */, + DAEB6B9D1943873100289F44 /* QuickTests */, + DA9876BE1A4C87200004AA17 /* QuickFocusedTests */, + 64076D1C1D6D7D0B00E2B499 /* QuickAfterSuiteTests */, + DAEB6B8F1943873100289F44 /* Products */, + 1F118D331BDCA645005013A2 /* Frameworks */, + ); + indentWidth = 4; + sourceTree = ""; + tabWidth = 4; + }; + DAEB6B8F1943873100289F44 /* Products */ = { + isa = PBXGroup; + children = ( + DAEB6B8E1943873100289F44 /* Quick.framework */, + DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */, + 5A5D117C19473F2100F6D13D /* Quick.framework */, + 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */, + DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */, + DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */, + 1F118CD51BDCA4AB005013A2 /* Quick.framework */, + 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */, + 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */, + 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */, + 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */, + 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + DAEB6B901943873100289F44 /* Quick */ = { + isa = PBXGroup; + children = ( + DA169E4619FF5DF100619816 /* Configuration */, + DA3124E119FCAEE8002858A7 /* DSL */, + DA408BDE19FF5599005DF92A /* Hooks */, + CD3451461E4703D4000C8633 /* QuickMain.swift */, + CD3451471E4703D4000C8633 /* QuickSpec.swift */, + 34F375A619515CA700CE1B99 /* World.swift */, + 34F3759E19515CA700CE1B99 /* Example.swift */, + DA02C91819A8073100093156 /* ExampleMetadata.swift */, + 34F3759F19515CA700CE1B99 /* ExampleGroup.swift */, + 34F3759C19515CA700CE1B99 /* Callsite.swift */, + DA6B30171A4DB0D500FFB148 /* Filter.swift */, + CE57CEDA1C430BD200D63004 /* QuickTestSuite.swift */, + CE57CED91C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift */, + CE57CED81C430BD200D63004 /* NSBundle+CurrentTestBundle.swift */, + DED3036A1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift */, + CE57CEDB1C430BD200D63004 /* URL+FileName.swift */, + 34C586071C4AC5E500D4F057 /* ErrorUtility.swift */, + DAEB6B911943873100289F44 /* Supporting Files */, + CE175D4D1E8D6B4900EB5E84 /* Behavior.swift */, + ); + name = Quick; + path = Sources/Quick; + sourceTree = ""; + }; + DAEB6B911943873100289F44 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DAEB6B921943873100289F44 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAEB6B9D1943873100289F44 /* QuickTests */ = { + isa = PBXGroup; + children = ( + DA8C00201A01E4B900CE58A6 /* QuickConfigurationTests.m */, + DA8F919419F31680006F6675 /* Helpers */, + DAEB6BCD194387D700289F44 /* Fixtures */, + DA8F919B19F3189D006F6675 /* FunctionalTests */, + F8100E941A1E4469007595ED /* Frameworks */, + DAEB6B9E1943873100289F44 /* Supporting Files */, + ); + name = QuickTests; + path = Tests/QuickTests/QuickTests; + sourceTree = ""; + }; + DAEB6B9E1943873100289F44 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + DAEB6B9F1943873100289F44 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + DAEB6BCD194387D700289F44 /* Fixtures */ = { + isa = PBXGroup; + children = ( + DA8F91AD19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift */, + CE4A578D1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift */, + ); + path = Fixtures; + sourceTree = ""; + }; + F8100E941A1E4469007595ED /* Frameworks */ = { + isa = PBXGroup; + children = ( + F8100E901A1E4447007595ED /* Nimble.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F118CD21BDCA4AB005013A2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D2B1BDCA5B6005013A2 /* Quick.h in Headers */, + 1F118D2A1BDCA5B6005013A2 /* QCKDSL.h in Headers */, + 1F118D2C1BDCA5B6005013A2 /* QuickSpec.h in Headers */, + 1F118D291BDCA5B6005013A2 /* QuickConfiguration.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117919473F2100F6D13D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714FF19FF6A62005905B8 /* QuickConfiguration.h in Headers */, + DA3124E919FCAEE8002858A7 /* QCKDSL.h in Headers */, + 34F375B819515CA700CE1B99 /* QuickSpec.h in Headers */, + 5A5D11A7194740E000F6D13D /* Quick.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8B1943873100289F44 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714FE19FF6A62005905B8 /* QuickConfiguration.h in Headers */, + DA3124E819FCAEE8002858A7 /* QCKDSL.h in Headers */, + 34F375B719515CA700CE1B99 /* QuickSpec.h in Headers */, + DAEB6B941943873100289F44 /* Quick.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CE61BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick-tvOS" */; + buildPhases = ( + 1F118CD01BDCA4AB005013A2 /* Sources */, + 1F118CD11BDCA4AB005013A2 /* Frameworks */, + 1F118CD21BDCA4AB005013A2 /* Headers */, + 1F118CD31BDCA4AB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-tvOS"; + productName = "Quick-tvOS"; + productReference = 1F118CD51BDCA4AB005013A2 /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + 1F118CDD1BDCA4AB005013A2 /* Quick - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CE91BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick - tvOSTests" */; + buildPhases = ( + 1F118CDA1BDCA4AB005013A2 /* Sources */, + 1F118CDB1BDCA4AB005013A2 /* Frameworks */, + 1F118CDC1BDCA4AB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F118CE11BDCA4AB005013A2 /* PBXTargetDependency */, + ); + name = "Quick - tvOSTests"; + productName = "Quick-tvOSTests"; + productReference = 1F118CDE1BDCA4AB005013A2 /* Quick - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 1F118CEF1BDCA4BB005013A2 /* QuickFocused - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F118CF81BDCA4BC005013A2 /* Build configuration list for PBXNativeTarget "QuickFocused - tvOSTests" */; + buildPhases = ( + 1F118CEC1BDCA4BB005013A2 /* Sources */, + 1F118CED1BDCA4BB005013A2 /* Frameworks */, + 1F118CEE1BDCA4BB005013A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F118CF71BDCA4BB005013A2 /* PBXTargetDependency */, + ); + name = "QuickFocused - tvOSTests"; + productName = "QuickFocused-tvOSTests"; + productReference = 1F118CF01BDCA4BB005013A2 /* QuickFocused - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 5A5D117B19473F2100F6D13D /* Quick-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */; + buildPhases = ( + 5A5D117719473F2100F6D13D /* Sources */, + 5A5D117819473F2100F6D13D /* Frameworks */, + 5A5D117919473F2100F6D13D /* Headers */, + 5A5D117A19473F2100F6D13D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-iOS"; + productName = "Quick-iOS"; + productReference = 5A5D117C19473F2100F6D13D /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + 5A5D118519473F2100F6D13D /* Quick - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick - iOSTests" */; + buildPhases = ( + 5A5D118219473F2100F6D13D /* Sources */, + 5A5D118319473F2100F6D13D /* Frameworks */, + 5A5D118419473F2100F6D13D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5A5D118919473F2100F6D13D /* PBXTargetDependency */, + 5A5D11F0194741B500F6D13D /* PBXTargetDependency */, + 5A5D11F2194741B500F6D13D /* PBXTargetDependency */, + 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */, + 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */, + 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */, + 04DC97F7194B831200CE00B6 /* PBXTargetDependency */, + 04DC97FB194B834100CE00B6 /* PBXTargetDependency */, + 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */, + 04DC9803194B836300CE00B6 /* PBXTargetDependency */, + 04DC9807194B838700CE00B6 /* PBXTargetDependency */, + ); + name = "Quick - iOSTests"; + productName = "Quick-iOSTests"; + productReference = 5A5D118619473F2100F6D13D /* Quick - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076CE51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076CF21D6D7C2000E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - macOSTests" */; + buildPhases = ( + 64076CE81D6D7C2000E2B499 /* Sources */, + 64076CEE1D6D7C2000E2B499 /* Frameworks */, + 64076CF11D6D7C2000E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076CE61D6D7C2000E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - macOSTests"; + productName = "QuickFocused-macOSTests"; + productReference = 64076CF51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076CF81D6D7CD600E2B499 /* QuickAfterSuite - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076D051D6D7CD600E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - iOSTests" */; + buildPhases = ( + 64076CFB1D6D7CD600E2B499 /* Sources */, + 64076D011D6D7CD600E2B499 /* Frameworks */, + 64076D041D6D7CD600E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076CF91D6D7CD600E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - iOSTests"; + productName = "QuickFocused-iOSTests"; + productReference = 64076D081D6D7CD600E2B499 /* QuickAfterSuite - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 64076D0A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 64076D171D6D7CEA00E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - tvOSTests" */; + buildPhases = ( + 64076D0D1D6D7CEA00E2B499 /* Sources */, + 64076D131D6D7CEA00E2B499 /* Frameworks */, + 64076D161D6D7CEA00E2B499 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64076D0B1D6D7CEA00E2B499 /* PBXTargetDependency */, + ); + name = "QuickAfterSuite - tvOSTests"; + productName = "QuickFocused-tvOSTests"; + productReference = 64076D1A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DA5663E71A4C8D8500193C88 /* QuickFocused - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA5663F31A4C8D8500193C88 /* Build configuration list for PBXNativeTarget "QuickFocused - macOSTests" */; + buildPhases = ( + DA5663E41A4C8D8500193C88 /* Sources */, + DA5663E51A4C8D8500193C88 /* Frameworks */, + DA5663E61A4C8D8500193C88 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DA5663F01A4C8D8500193C88 /* PBXTargetDependency */, + ); + name = "QuickFocused - macOSTests"; + productName = "QuickFocused-macOSTests"; + productReference = DA5663E81A4C8D8500193C88 /* QuickFocused - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DA9876B11A4C70EB0004AA17 /* QuickFocused - iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA9876BD1A4C70EB0004AA17 /* Build configuration list for PBXNativeTarget "QuickFocused - iOSTests" */; + buildPhases = ( + DA9876AE1A4C70EB0004AA17 /* Sources */, + DA9876AF1A4C70EB0004AA17 /* Frameworks */, + DA9876B01A4C70EB0004AA17 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DA9876BA1A4C70EB0004AA17 /* PBXTargetDependency */, + ); + name = "QuickFocused - iOSTests"; + productName = "QuickFocused-iOSTests"; + productReference = DA9876B21A4C70EB0004AA17 /* QuickFocused - iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DAEB6B8D1943873100289F44 /* Quick-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-macOS" */; + buildPhases = ( + DAEB6B891943873100289F44 /* Sources */, + DAEB6B8A1943873100289F44 /* Frameworks */, + DAEB6B8B1943873100289F44 /* Headers */, + DAEB6B8C1943873100289F44 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Quick-macOS"; + productName = Quick; + productReference = DAEB6B8E1943873100289F44 /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + DAEB6B981943873100289F44 /* Quick - macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick - macOSTests" */; + buildPhases = ( + DAEB6B951943873100289F44 /* Sources */, + DAEB6B961943873100289F44 /* Frameworks */, + DAEB6B971943873100289F44 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DAEB6B9C1943873100289F44 /* PBXTargetDependency */, + 047655521949F4CB00B288BB /* PBXTargetDependency */, + 047655541949F4CB00B288BB /* PBXTargetDependency */, + 04765556194A327000B288BB /* PBXTargetDependency */, + 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */, + 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */, + 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */, + 04DC97F9194B834000CE00B6 /* PBXTargetDependency */, + 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */, + 04DC9801194B836100CE00B6 /* PBXTargetDependency */, + 04DC9805194B838400CE00B6 /* PBXTargetDependency */, + 04DC9809194B838B00CE00B6 /* PBXTargetDependency */, + 93625F391951DDC8006B1FE1 /* PBXTargetDependency */, + ); + name = "Quick - macOSTests"; + productName = QuickTests; + productReference = DAEB6B991943873100289F44 /* Quick - macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DAEB6B851943873100289F44 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0810; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Brian Ivan Gesiak"; + TargetAttributes = { + 1F118CD41BDCA4AB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F118CDD1BDCA4AB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F118CEF1BDCA4BB005013A2 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 5A5D117B19473F2100F6D13D = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 5A5D118519473F2100F6D13D = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = 5A5D117B19473F2100F6D13D; + }; + 732D8D691E516780008558BD = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; + }; + DA5663E71A4C8D8500193C88 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + DA9876B11A4C70EB0004AA17 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + DAEB6B8D1943873100289F44 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + DAEB6B981943873100289F44 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = DAEB6B8D1943873100289F44; + }; + }; + }; + buildConfigurationList = DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DAEB6B841943873100289F44; + productRefGroup = DAEB6B8F1943873100289F44 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DAEB6B8D1943873100289F44 /* Quick-macOS */, + DAEB6B981943873100289F44 /* Quick - macOSTests */, + DA5663E71A4C8D8500193C88 /* QuickFocused - macOSTests */, + 64076CE51D6D7C2000E2B499 /* QuickAfterSuite - macOSTests */, + 5A5D117B19473F2100F6D13D /* Quick-iOS */, + 5A5D118519473F2100F6D13D /* Quick - iOSTests */, + DA9876B11A4C70EB0004AA17 /* QuickFocused - iOSTests */, + 64076CF81D6D7CD600E2B499 /* QuickAfterSuite - iOSTests */, + 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */, + 1F118CDD1BDCA4AB005013A2 /* Quick - tvOSTests */, + 1F118CEF1BDCA4BB005013A2 /* QuickFocused - tvOSTests */, + 64076D0A1D6D7CEA00E2B499 /* QuickAfterSuite - tvOSTests */, + 732D8D691E516780008558BD /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F118CD31BDCA4AB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDC1BDCA4AB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CEE1BDCA4BB005013A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117A19473F2100F6D13D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118419473F2100F6D13D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CF11D6D7C2000E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D041D6D7CD600E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D161D6D7CEA00E2B499 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E61A4C8D8500193C88 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876B01A4C70EB0004AA17 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B8C1943873100289F44 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B971943873100289F44 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 732D8D6D1E516789008558BD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F118CD01BDCA4AB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D031BDCA536005013A2 /* World.swift in Sources */, + CE590E201C431FE400253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + 1F118CFC1BDCA536005013A2 /* Configuration.swift in Sources */, + 1F118D021BDCA536005013A2 /* SuiteHooks.swift in Sources */, + 1F118CFB1BDCA536005013A2 /* QuickConfiguration.m in Sources */, + 34C5860A1C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + 1F118D041BDCA536005013A2 /* Example.swift in Sources */, + 1F118CFF1BDCA536005013A2 /* QCKDSL.m in Sources */, + DED3036D1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + CE590E211C431FE400253D19 /* NSBundle+CurrentTestBundle.swift in Sources */, + 1F118D071BDCA536005013A2 /* Callsite.swift in Sources */, + CE590E231C431FE400253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + 1F118D081BDCA536005013A2 /* Filter.swift in Sources */, + 1F118CFD1BDCA536005013A2 /* World+DSL.swift in Sources */, + CE590E221C431FE400253D19 /* URL+FileName.swift in Sources */, + 1F118CFE1BDCA536005013A2 /* DSL.swift in Sources */, + 7B44ADC01C5444940007AF2E /* HooksPhase.swift in Sources */, + 1F118D001BDCA536005013A2 /* Closures.swift in Sources */, + 1F118D051BDCA536005013A2 /* ExampleMetadata.swift in Sources */, + 1F118D061BDCA536005013A2 /* ExampleGroup.swift in Sources */, + CE175D501E8D6B4900EB5E84 /* Behavior.swift in Sources */, + CE590E1F1C431FE400253D19 /* QuickTestSuite.swift in Sources */, + 1F118D091BDCA536005013A2 /* QuickSpec.m in Sources */, + 1F118D011BDCA536005013A2 /* ExampleHooks.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CDA1BDCA4AB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D381BDCA6E1005013A2 /* Configuration+BeforeEachTests.swift in Sources */, + 1F118D121BDCA556005013A2 /* ItTests.swift in Sources */, + 1F118D1C1BDCA556005013A2 /* BeforeSuiteTests.swift in Sources */, + 1F118D1D1BDCA556005013A2 /* BeforeSuiteTests+ObjC.m in Sources */, + 1F118D0E1BDCA547005013A2 /* QCKSpecRunner.m in Sources */, + CE4A57931EA725420063C0D4 /* BehaviorTests.swift in Sources */, + 1F118D141BDCA556005013A2 /* FailureTests+ObjC.m in Sources */, + CE4A57911EA7252E0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DED3037F1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + 1F118D0F1BDCA54B005013A2 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + 1F118D101BDCA556005013A2 /* Configuration+AfterEach.swift in Sources */, + 1F118D1A1BDCA556005013A2 /* PendingTests.swift in Sources */, + 1F118D171BDCA556005013A2 /* BeforeEachTests+ObjC.m in Sources */, + 1F118D231BDCA556005013A2 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + 1F118D151BDCA556005013A2 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 1F118D131BDCA556005013A2 /* ItTests+ObjC.m in Sources */, + 1F118D191BDCA556005013A2 /* AfterEachTests+ObjC.m in Sources */, + 1F118D221BDCA556005013A2 /* SharedExamples+BeforeEachTests.swift in Sources */, + AE4E58171C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8651CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 1F118D211BDCA556005013A2 /* SharedExamplesTests+ObjC.m in Sources */, + 1F118D201BDCA556005013A2 /* SharedExamplesTests.swift in Sources */, + 1F118D0C1BDCA543005013A2 /* QuickConfigurationTests.m in Sources */, + 1F118D391BDCA6E6005013A2 /* Configuration+BeforeEach.swift in Sources */, + CD564DA220B5B09E00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */, + 1F118D181BDCA556005013A2 /* AfterEachTests.swift in Sources */, + 1F118D1B1BDCA556005013A2 /* PendingTests+ObjC.m in Sources */, + 34C586051C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A591C11726F00633E2B /* DescribeTests.swift in Sources */, + 1F118D111BDCA556005013A2 /* Configuration+AfterEachTests.swift in Sources */, + 1F118D161BDCA556005013A2 /* BeforeEachTests.swift in Sources */, + DA5CBB4B1EAFA61D00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358D01C3D4FC000A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F118CEC1BDCA4BB005013A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F118D0D1BDCA547005013A2 /* QCKSpecRunner.m in Sources */, + 34C586061C4ABD4100D4F057 /* XCTestCaseProvider.swift in Sources */, + 1F118D241BDCA561005013A2 /* FocusedTests.swift in Sources */, + 1F118D251BDCA561005013A2 /* FocusedTests+ObjC.m in Sources */, + AE4E58181C73097E00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D117719473F2100F6D13D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE590E1B1C431FE300253D19 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + DA3124EB19FCAEE8002858A7 /* QCKDSL.m in Sources */, + DA408BE319FF5599005DF92A /* Closures.swift in Sources */, + DA02C91A19A8073100093156 /* ExampleMetadata.swift in Sources */, + 34C586091C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + DA408BE719FF5599005DF92A /* SuiteHooks.swift in Sources */, + 34F375BA19515CA700CE1B99 /* QuickSpec.m in Sources */, + DED3036C1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + CE590E1C1C431FE300253D19 /* NSBundle+CurrentTestBundle.swift in Sources */, + DAE7150119FF6A62005905B8 /* QuickConfiguration.m in Sources */, + CE590E1E1C431FE300253D19 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + 34F375A819515CA700CE1B99 /* Callsite.swift in Sources */, + 34F375AE19515CA700CE1B99 /* ExampleGroup.swift in Sources */, + CE590E1D1C431FE300253D19 /* URL+FileName.swift in Sources */, + 34F375BC19515CA700CE1B99 /* World.swift in Sources */, + DA169E4919FF5DF100619816 /* Configuration.swift in Sources */, + 7B44ADBF1C5444940007AF2E /* HooksPhase.swift in Sources */, + DA3124ED19FCAEE8002858A7 /* World+DSL.swift in Sources */, + DA408BE519FF5599005DF92A /* ExampleHooks.swift in Sources */, + 34F375AC19515CA700CE1B99 /* Example.swift in Sources */, + CE175D4F1E8D6B4900EB5E84 /* Behavior.swift in Sources */, + CE590E1A1C431FE300253D19 /* QuickTestSuite.swift in Sources */, + DA3124E719FCAEE8002858A7 /* DSL.swift in Sources */, + DA6B30191A4DB0D500FFB148 /* Filter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5A5D118219473F2100F6D13D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714F819FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, + DAA7C0D719F777EB0093D1D9 /* BeforeEachTests.swift in Sources */, + DA8F919A19F31680006F6675 /* QCKSpecRunner.m in Sources */, + DA8940F11B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 4728253C1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */, + DAE714F119FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, + DED3037E1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + DA05D61119F73A3800771050 /* AfterEachTests.swift in Sources */, + DAB0137019FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, + DA8F91A619F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, + DA8C00221A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, + CE4A578A1EA5DC270063C0D4 /* BehaviorTests.swift in Sources */, + DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */, + DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, + DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */, + 4748E8951A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + CE4A578E1EA7251C0063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DA8F91AF19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + DAE714FB19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, + AE4E58151C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8641CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 471590411A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */, + DA8F919E19F31921006F6675 /* FailureTests+ObjC.m in Sources */, + DAE714F419FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, + CD564DA120B5B09D00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */, + 479C31E41A36172700DA8718 /* ItTests+ObjC.m in Sources */, + 34C586031C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A581C11726F00633E2B /* DescribeTests.swift in Sources */, + 47FAEA371A3F49EB005A1D2F /* BeforeEachTests+ObjC.m in Sources */, + 470D6ECC1A43442900043E50 /* AfterEachTests+ObjC.m in Sources */, + 47876F7E1A49AD71002575C7 /* BeforeSuiteTests+ObjC.m in Sources */, + DA5CBB4A1EAFA61C00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358CF1C3D4FBE00A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CE81D6D7C2000E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D211D6D7E4D00E2B499 /* AfterSuiteTests.swift in Sources */, + CD264DBD1DDA147A0038B0EB /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076CFB1D6D7CD600E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D221D6D7E5B00E2B499 /* AfterSuiteTests.swift in Sources */, + 64076D261D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64076D0D1D6D7CEA00E2B499 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 64076D231D6D7E6B00E2B499 /* AfterSuiteTests.swift in Sources */, + 64076D271D6D80B500E2B499 /* AfterSuiteTests+ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA5663E41A4C8D8500193C88 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA07722E1A4E5B7B0098839D /* QCKSpecRunner.m in Sources */, + 34C586021C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */, + DA5663F41A4C8D9A00193C88 /* FocusedTests.swift in Sources */, + DAF28BC31A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */, + AE4E58141C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA9876AE1A4C70EB0004AA17 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA07722F1A4E5B7C0098839D /* QCKSpecRunner.m in Sources */, + 34C586041C4ABD4000D4F057 /* XCTestCaseProvider.swift in Sources */, + DA9876C11A4C87200004AA17 /* FocusedTests.swift in Sources */, + DAF28BC41A4DB8EC00A5D9BF /* FocusedTests+ObjC.m in Sources */, + AE4E58161C73097C00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B891943873100289F44 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CE57CEDE1C430BD200D63004 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + DA3124EA19FCAEE8002858A7 /* QCKDSL.m in Sources */, + DA408BE219FF5599005DF92A /* Closures.swift in Sources */, + CE57CEDD1C430BD200D63004 /* NSBundle+CurrentTestBundle.swift in Sources */, + DA02C91919A8073100093156 /* ExampleMetadata.swift in Sources */, + CE57CEDF1C430BD200D63004 /* QuickTestSuite.swift in Sources */, + 34C586081C4AC5E500D4F057 /* ErrorUtility.swift in Sources */, + DED3036B1DF6C66B0041394E /* NSString+C99ExtendedIdentifier.swift in Sources */, + DA408BE619FF5599005DF92A /* SuiteHooks.swift in Sources */, + 34F375B919515CA700CE1B99 /* QuickSpec.m in Sources */, + CE57CEE11C430BD200D63004 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + DAE7150019FF6A62005905B8 /* QuickConfiguration.m in Sources */, + 34F375A719515CA700CE1B99 /* Callsite.swift in Sources */, + CE57CEE01C430BD200D63004 /* URL+FileName.swift in Sources */, + 34F375AD19515CA700CE1B99 /* ExampleGroup.swift in Sources */, + 34F375BB19515CA700CE1B99 /* World.swift in Sources */, + DA169E4819FF5DF100619816 /* Configuration.swift in Sources */, + 7B44ADBE1C5444940007AF2E /* HooksPhase.swift in Sources */, + DA3124EC19FCAEE8002858A7 /* World+DSL.swift in Sources */, + DA408BE419FF5599005DF92A /* ExampleHooks.swift in Sources */, + CE175D4E1E8D6B4900EB5E84 /* Behavior.swift in Sources */, + 34F375AB19515CA700CE1B99 /* Example.swift in Sources */, + DA3124E619FCAEE8002858A7 /* DSL.swift in Sources */, + DA6B30181A4DB0D500FFB148 /* Filter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DAEB6B951943873100289F44 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAE714F719FF6812005905B8 /* Configuration+AfterEach.swift in Sources */, + DAB067E919F7801C00F970AC /* BeforeEachTests.swift in Sources */, + DA8F919919F31680006F6675 /* QCKSpecRunner.m in Sources */, + DA8940F01B35B1FA00161061 /* FailureUsingXCTAssertTests+ObjC.m in Sources */, + 4728253B1A5EECCE008DC74F /* SharedExamplesTests+ObjC.m in Sources */, + CE4A57941EA725440063C0D4 /* BehaviorTests.swift in Sources */, + DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.swift in Sources */, + CE4A57921EA725300063C0D4 /* FunctionalTests_BehaviorTests_Behaviors.swift in Sources */, + DED3037D1DF6CF140041394E /* BundleModuleNameTests.swift in Sources */, + DA05D61019F73A3800771050 /* AfterEachTests.swift in Sources */, + DAB0136F19FC4315006AFBEE /* SharedExamples+BeforeEachTests.swift in Sources */, + DA8F91A519F3208B006F6675 /* BeforeSuiteTests.swift in Sources */, + DA8C00211A01E4B900CE58A6 /* QuickConfigurationTests.m in Sources */, + DAA63EA319F7637300CD0A3B /* PendingTests.swift in Sources */, + DA8F91AB19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, + DA7AE6F119FC493F000AFDCE /* ItTests.swift in Sources */, + 4748E8941A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m in Sources */, + DA8F91AE19F32CE2006F6675 /* FunctionalTests_SharedExamplesTests_SharedExamples.swift in Sources */, + DAE714FA19FF682A005905B8 /* Configuration+AfterEachTests.swift in Sources */, + AE4E58131C73097A00420A2E /* XCTestObservationCenter+QCKSuspendObservation.m in Sources */, + AED9C8631CC8A7BD00432F62 /* CrossReferencingSpecs.swift in Sources */, + 471590401A488F3F00FBA644 /* PendingTests+ObjC.m in Sources */, + DA8F919D19F31921006F6675 /* FailureTests+ObjC.m in Sources */, + DAE714F319FF65E7005905B8 /* Configuration+BeforeEach.swift in Sources */, + CD564DA020B5B09C00C15E6B /* QuickSpec+QuickSpec_MethodList.m in Sources */, + 479C31E31A36171B00DA8718 /* ItTests+ObjC.m in Sources */, + 34C586011C4ABD3F00D4F057 /* XCTestCaseProvider.swift in Sources */, + 8D010A571C11726F00633E2B /* DescribeTests.swift in Sources */, + 47FAEA361A3F49E6005A1D2F /* BeforeEachTests+ObjC.m in Sources */, + 470D6ECB1A43442400043E50 /* AfterEachTests+ObjC.m in Sources */, + 47876F7D1A49AD63002575C7 /* BeforeSuiteTests+ObjC.m in Sources */, + DA5CBB491EAFA61A00297C9E /* CurrentSpecTests.swift in Sources */, + 7B5358CE1C3D4FBC00A23FAA /* ContextTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 047655521949F4CB00B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 047655511949F4CB00B288BB /* PBXContainerItemProxy */; + }; + 047655541949F4CB00B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 047655531949F4CB00B288BB /* PBXContainerItemProxy */; + }; + 04765556194A327000B288BB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04765555194A327000B288BB /* PBXContainerItemProxy */; + }; + 04DC97E5194B4A6000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97E4194B4A6000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97E7194B4A6000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97E6194B4A6000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97E9194B4B7E00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97E8194B4B7E00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97EB194B4B9B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97EA194B4B9B00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F1194B82DB00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97F0194B82DB00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F3194B82DE00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97F2194B82DE00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F7194B831200CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97F6194B831200CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97F9194B834000CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97F8194B834000CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FB194B834100CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97FA194B834100CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FD194B834B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC97FC194B834B00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC97FF194B835E00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC97FE194B835E00CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9801194B836100CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9800194B836100CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9803194B836300CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC9802194B836300CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9805194B838400CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9804194B838400CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9807194B838700CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 04DC9806194B838700CE00B6 /* PBXContainerItemProxy */; + }; + 04DC9809194B838B00CE00B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 04DC9808194B838B00CE00B6 /* PBXContainerItemProxy */; + }; + 1F118CE11BDCA4AB005013A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 1F118CE01BDCA4AB005013A2 /* PBXContainerItemProxy */; + }; + 1F118CF71BDCA4BB005013A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 1F118CF61BDCA4BB005013A2 /* PBXContainerItemProxy */; + }; + 5A5D118919473F2100F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D118819473F2100F6D13D /* PBXContainerItemProxy */; + }; + 5A5D11F0194741B500F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D11EF194741B500F6D13D /* PBXContainerItemProxy */; + }; + 5A5D11F2194741B500F6D13D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 5A5D11F1194741B500F6D13D /* PBXContainerItemProxy */; + }; + 64076CE61D6D7C2000E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 64076CE71D6D7C2000E2B499 /* PBXContainerItemProxy */; + }; + 64076CF91D6D7CD600E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = 64076CFA1D6D7CD600E2B499 /* PBXContainerItemProxy */; + }; + 64076D0B1D6D7CEA00E2B499 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1F118CD41BDCA4AB005013A2 /* Quick-tvOS */; + targetProxy = 64076D0C1D6D7CEA00E2B499 /* PBXContainerItemProxy */; + }; + 93625F391951DDC8006B1FE1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = 93625F381951DDC8006B1FE1 /* PBXContainerItemProxy */; + }; + DA5663F01A4C8D8500193C88 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = DA5663EF1A4C8D8500193C88 /* PBXContainerItemProxy */; + }; + DA9876BA1A4C70EB0004AA17 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A5D117B19473F2100F6D13D /* Quick-iOS */; + targetProxy = DA9876B91A4C70EB0004AA17 /* PBXContainerItemProxy */; + }; + DAEB6B9C1943873100289F44 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DAEB6B8D1943873100289F44 /* Quick-macOS */; + targetProxy = DAEB6B9B1943873100289F44 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1F118CE71BDCA4AB005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = 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", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Quick; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CE81BDCA4AB005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + COPY_PHASE_STRIP = NO; + 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", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Quick; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1F118CEA1BDCA4AB005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CEB1BDCA4AB005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1F118CF91BDCA4BC005013A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 1F118CFA1BDCA4BC005013A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5A5D118F19473F2100F6D13D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = 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", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 5A5D119019473F2100F6D13D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = 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", + "$(inherited)", + ); + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5A5D119119473F2100F6D13D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 5A5D119219473F2100F6D13D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 64076CF31D6D7C2000E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 64076CF41D6D7C2000E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 64076D061D6D7CD600E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 64076D071D6D7CD600E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 64076D181D6D7CEA00E2B499 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 64076D191D6D7CEA00E2B499 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/Nimble/build/Debug-appletvos", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Tests/QuickTests/QuickAfterSuiteTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 732D8D6B1E516780008558BD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 732D8D6C1E516780008558BD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + DA5663F11A4C8D8500193C88 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DA5663F21A4C8D8500193C88 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + DA9876BB1A4C70EB0004AA17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DA9876BC1A4C70EB0004AA17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickFocusedTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DAEB6BA21943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DAEB6BA31943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 3.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DAEB6BA51943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = 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", + "$(inherited)", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + DAEB6BA61943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = 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", + "$(inherited)", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Quick/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Xlinker", + "-no_application_extension", + ); + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_MODULE_NAME = Quick; + PRODUCT_NAME = Quick; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + DAEB6BA81943873200289F44 /* Debug */ = { + isa = XCBuildConfiguration; + 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/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DAEB6BA91943873200289F44 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/QuickTests/QuickTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "io.quick.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F118CE61BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CE71BDCA4AB005013A2 /* Debug */, + 1F118CE81BDCA4AB005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F118CE91BDCA4AB005013A2 /* Build configuration list for PBXNativeTarget "Quick - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CEA1BDCA4AB005013A2 /* Debug */, + 1F118CEB1BDCA4AB005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F118CF81BDCA4BC005013A2 /* Build configuration list for PBXNativeTarget "QuickFocused - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F118CF91BDCA4BC005013A2 /* Debug */, + 1F118CFA1BDCA4BC005013A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5A5D119319473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5A5D118F19473F2100F6D13D /* Debug */, + 5A5D119019473F2100F6D13D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5A5D119419473F2100F6D13D /* Build configuration list for PBXNativeTarget "Quick - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5A5D119119473F2100F6D13D /* Debug */, + 5A5D119219473F2100F6D13D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076CF21D6D7C2000E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076CF31D6D7C2000E2B499 /* Debug */, + 64076CF41D6D7C2000E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076D051D6D7CD600E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076D061D6D7CD600E2B499 /* Debug */, + 64076D071D6D7CD600E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 64076D171D6D7CEA00E2B499 /* Build configuration list for PBXNativeTarget "QuickAfterSuite - tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 64076D181D6D7CEA00E2B499 /* Debug */, + 64076D191D6D7CEA00E2B499 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 732D8D6A1E516780008558BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 732D8D6B1E516780008558BD /* Debug */, + 732D8D6C1E516780008558BD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DA5663F31A4C8D8500193C88 /* Build configuration list for PBXNativeTarget "QuickFocused - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA5663F11A4C8D8500193C88 /* Debug */, + DA5663F21A4C8D8500193C88 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DA9876BD1A4C70EB0004AA17 /* Build configuration list for PBXNativeTarget "QuickFocused - iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA9876BB1A4C70EB0004AA17 /* Debug */, + DA9876BC1A4C70EB0004AA17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6B881943873100289F44 /* Build configuration list for PBXProject "Quick" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA21943873200289F44 /* Debug */, + DAEB6BA31943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6BA41943873200289F44 /* Build configuration list for PBXNativeTarget "Quick-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA51943873200289F44 /* Debug */, + DAEB6BA61943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAEB6BA71943873200289F44 /* Build configuration list for PBXNativeTarget "Quick - macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAEB6BA81943873200289F44 /* Debug */, + DAEB6BA91943873200289F44 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DAEB6B851943873100289F44 /* Project object */; +} diff --git a/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a459aa8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme new file mode 100644 index 0000000..584e319 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme new file mode 100644 index 0000000..ce4dfe3 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme new file mode 100644 index 0000000..fcd9b81 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..48af53a --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Quick/Quick.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Quick/README.md b/Carthage/Checkouts/Quick/README.md new file mode 100644 index 0000000..e6dc0ad --- /dev/null +++ b/Carthage/Checkouts/Quick/README.md @@ -0,0 +1,88 @@ +![](http://f.cl.ly/items/0r1E192C1R0b2g2Q3h2w/QuickLogo_Color.png) + +[![Build Status](https://travis-ci.org/Quick/Quick.svg?branch=master)](https://travis-ci.org/Quick/Quick) +[![CocoaPods](https://img.shields.io/cocoapods/v/Quick.svg)](https://cocoapods.org/pods/Quick) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Platforms](https://img.shields.io/cocoapods/p/Quick.svg)](https://cocoapods.org/pods/Quick) + +Quick is a behavior-driven development framework for Swift and Objective-C. +Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo). + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/QuickSpec%20screenshot.png) + +```swift +// Swift + +import Quick +import Nimble + +class TableOfContentsSpec: QuickSpec { + override func spec() { + describe("the 'Documentation' directory") { + it("has everything you need to get started") { + let sections = Directory("Documentation").sections + expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups")) + expect(sections).to(contain("Installing Quick")) + } + + context("if it doesn't have what you're looking for") { + it("needs to be updated") { + let you = You(awesome: true) + expect{you.submittedAnIssue}.toEventually(beTruthy()) + } + } + } + } +} +``` +#### Nimble +Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md). + +## Swift Version + +Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project. + +|Swift version |Quick version |Nimble version | +|:--------------------|:---------------|:--------------| +|Swift 3 |v1.0.0 or later |v5.0.0 or later| +|Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 | + +## Documentation + +All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile: + +```rb +# Podfile + +use_frameworks! + +target "MyApp" do + # Normal libraries + + abstract_target 'Tests' do + inherit! :search_paths + target "MyAppTests" + target "MyAppUITests" + + pod 'Quick' + pod 'Nimble' + end +end +``` + +## Projects using Quick + +Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them. + +Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick). + +## Who uses Quick + +Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses? + +Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick). + + +## License + +Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details. diff --git a/Carthage/Checkouts/Quick/Rakefile b/Carthage/Checkouts/Quick/Rakefile new file mode 100644 index 0000000..051803e --- /dev/null +++ b/Carthage/Checkouts/Quick/Rakefile @@ -0,0 +1,72 @@ +def run(env = {}, command) + system(env, command) or raise "RAKE TASK FAILED: #{command}" +end + +def has_xcodebuild + system "which xcodebuild >/dev/null" +end + +def xcode_action + ENV["XCODE_ACTION"] || "build test" +end + +namespace "podspec" do + desc "Run lint for podspec" + task :lint do + run "bundle exec pod lib lint" + end +end + +namespace "test" do + desc "Run unit tests for all iOS targets" + task :ios do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-iOS -destination 'platform=iOS Simulator,name=iPhone 6' clean #{xcode_action}" + end + + desc "Run unit tests for all tvOS targets" + task :tvos do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 1080p' clean #{xcode_action}" + end + + desc "Run unit tests for all macOS targets" + task :macos do |t| + run "xcodebuild -workspace Quick.xcworkspace -scheme Quick-macOS clean #{xcode_action}" + end + + desc "Run unit tests for all macOS targets using static linking" + task :macos_static do |t| + run " MACH_O_TYPE=staticlib xcodebuild -workspace Quick.xcworkspace -scheme Quick-macOS clean #{xcode_action}" + end + + desc "Run unit tests for the current platform built by the Swift Package Manager" + task :swiftpm do |t| + env = { "SWIFT_PACKAGE_TEST_Quick" => "true" } + run env, "swift package clean && swift test" + end +end + +namespace "templates" do + install_dir = File.expand_path("~/Library/Developer/Xcode/Templates/File Templates/Quick") + src_dir = File.expand_path("../Quick Templates", __FILE__) + + desc "Install Quick templates" + task :install do + if File.exists? install_dir + raise "RAKE TASK FAILED: Quick templates are already installed at #{install_dir}" + else + mkdir_p install_dir + cp_r src_dir, install_dir + end + end + + desc "Uninstall Quick templates" + task :uninstall do + rm_rf install_dir + end +end + +if has_xcodebuild then + task default: ["test:ios", "test:tvos", "test:macos"] +else + task default: ["test:swiftpm"] +end diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift b/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift new file mode 100644 index 0000000..1d98702 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Behavior.swift @@ -0,0 +1,17 @@ +/** + A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` function with a context instance of the generic type. + */ + +open class Behavior { + + open static var name: String { return String(describing: self) } + /** + override this method in your behavior to define a set of reusable examples. + + This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + + - parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject. + */ + open class func spec(_ aContext: @escaping () -> Context) {} +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift b/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift new file mode 100644 index 0000000..f5e3711 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift @@ -0,0 +1,45 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _CallsiteBase: NSObject {} + #else + public class _CallsiteBase: NSObject {} + #endif +#else +public class _CallsiteBase: NSObject {} +#endif + +/** + An object encapsulating the file and line number at which + a particular example is defined. +*/ +final public class Callsite: _CallsiteBase { + /** + The absolute path of the file in which an example is defined. + */ + public let file: String + + /** + The line number on which an example is defined. + */ + public let line: UInt + + internal init(file: String, line: UInt) { + self.file = file + self.line = line + } +} + +extension Callsite { + /** + Returns a boolean indicating whether two Callsite objects are equal. + If two callsites are in the same file and on the same line, they must be equal. + */ + @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool { + return lhs.file == rhs.file && lhs.line == rhs.line + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift b/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift new file mode 100644 index 0000000..dbb95f1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift @@ -0,0 +1,161 @@ +import Foundation + +/** + A closure that temporarily exposes a Configuration object within + the scope of the closure. +*/ +public typealias QuickConfigurer = (_ configuration: Configuration) -> Void + +/** + A closure that, given metadata about an example, returns a boolean value + indicating whether that example should be run. +*/ +public typealias ExampleFilter = (_ example: Example) -> Bool + +/** + A configuration encapsulates various options you can use + to configure Quick's behavior. +*/ +final public class Configuration: NSObject { + internal let exampleHooks = ExampleHooks() + internal let suiteHooks = SuiteHooks() + internal var exclusionFilters: [ExampleFilter] = [ { example in + if let pending = example.filterFlags[Filter.pending] { + return pending + } else { + return false + } + }] + internal var inclusionFilters: [ExampleFilter] = [ { example in + if let focused = example.filterFlags[Filter.focused] { + return focused + } else { + return false + } + }] + + /** + Run all examples if none match the configured filters. True by default. + */ + public var runAllWhenEverythingFiltered = true + + /** + Registers an inclusion filter. + + All examples are filtered using all inclusion filters. + The remaining examples are run. If no examples remain, all examples are run. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be included in the examples + that are run. + */ + public func include(_ filter: @escaping ExampleFilter) { + inclusionFilters.append(filter) + } + + /** + Registers an exclusion filter. + + All examples that remain after being filtered by the inclusion filters are + then filtered via all exclusion filters. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be excluded from the examples + that are run. + */ + public func exclude(_ filter: @escaping ExampleFilter) { + exclusionFilters.append(filter) + } + + /** + Identical to Quick.Configuration.beforeEach, except the closure is + provided with metadata on the example that the closure is being run + prior to. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(beforeEachWithMetadata:) + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#else + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#endif + + /** + Like Quick.DSL.beforeEach, this configures Quick to execute the + given closure before each example that is run. The closure + passed to this method is executed before each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run before each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which beforeEach closures are evaluated + either. Mulitple beforeEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + exampleHooks.appendBefore(closure) + } + + /** + Identical to Quick.Configuration.afterEach, except the closure + is provided with metadata on the example that the closure is being + run after. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(afterEachWithMetadata:) + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#else + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#endif + + /** + Like Quick.DSL.afterEach, this configures Quick to execute the + given closure after each example that is run. The closure + passed to this method is executed after each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run after each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which afterEach closures are evaluated + either. Mulitple afterEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func afterEach(_ closure: @escaping AfterExampleClosure) { + exampleHooks.appendAfter(closure) + } + + /** + Like Quick.DSL.beforeSuite, this configures Quick to execute + the given closure prior to any and all examples that are run. + The two methods are functionally equivalent. + */ + public func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + /** + Like Quick.DSL.afterSuite, this configures Quick to execute + the given closure after all examples have been run. + The two methods are functionally equivalent. + */ + public func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift b/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift new file mode 100644 index 0000000..3da6be2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift @@ -0,0 +1,39 @@ +import Foundation +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE + +open class QuickConfiguration: NSObject { + open class func configure(_ configuration: Configuration) {} +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +internal func qck_enumerateSubclasses(_ klass: T.Type, block: (T.Type) -> Void) { + var classesCount = objc_getClassList(nil, 0) + + guard classesCount > 0 else { + return + } + + let classes = UnsafeMutablePointer.allocate(capacity: Int(classesCount)) + classesCount = objc_getClassList(AutoreleasingUnsafeMutablePointer(classes), classesCount) + + var subclass: AnyClass! + for i in 0.. Void) { + World.sharedWorld.sharedExamples(name) { _ in closure() } +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + - parameter name: The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + - parameter closure: A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + + The closure takes a SharedExampleContext as an argument. This context is a function + that can be executed to retrieve parameters passed in via an `itBehavesLike` function. +*/ +public func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + World.sharedWorld.sharedExamples(name, closure: closure) +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + - parameter description: An arbitrary string describing the example group. + - parameter closure: A closure that can contain other examples. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. +*/ +public func describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.describe(description, flags: flags, closure: closure) +} + +/** + Defines an example group. Equivalent to `describe`. +*/ +public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.context(description, flags: flags, closure: closure) +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run prior to each example. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + World.sharedWorld.beforeEach(closure) +} + +/** + Identical to Quick.DSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + World.sharedWorld.beforeEach(closure: closure) +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run after each example. +*/ +public func afterEach(_ closure: @escaping AfterExampleClosure) { + World.sharedWorld.afterEach(closure) +} + +/** + Identical to Quick.DSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. +*/ +public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + World.sharedWorld.afterEach(closure: closure) +} + +/** + Defines an example. Examples use assertions to demonstrate how code should + behave. These are like "tests" in XCTest. + + - parameter description: An arbitrary string describing what the example is meant to specify. + - parameter closure: A closure that can contain assertions. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the example. A sensible default is provided. + - parameter line: The line containing the example. A sensible default is provided. +*/ +public func it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + itBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + This function also passes those shared examples a context that can be evaluated to give the shared + examples extra information on the subject of the example. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter sharedExampleContext: A closure that, when evaluated, returns key-value pairs that provide the + shared examples with extra information on the subject of the example. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} + +/** + Inserts the examples defined using a `Behavior` into the current example group. + The shared examples are executed at this location, as if they were written out manually. + This function also passes a strongly-typed context that can be evaluated to give the shared examples extra information on the subject of the example. + + - parameter behavior: The type of `Behavior` class defining the example group to be executed. + - parameter context: A closure that, when evaluated, returns an instance of `Behavior`'s context type to provide its example group with extra information on the subject of the example. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. + */ +public func itBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.itBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + - parameter description: An arbitrary string describing the example or example group. + - parameter closure: A closure that will not be evaluated. +*/ +public func pending(_ description: String, closure: () -> Void) { + World.sharedWorld.pending(description, closure: closure) +} + +/** + Use this to quickly mark a `describe` closure as pending. + This disables all examples within the closure. +*/ +public func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + World.sharedWorld.xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark a `context` closure as pending. + This disables all examples within the closure. +*/ +public func xcontext(_ description: String, flags: FilterFlags, closure: () -> Void) { + xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark an `it` closure as pending. + This disables the example and ensures the code within the closure is never run. +*/ +public func xit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.xit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quicklu mark an `itBehavesLike` closure as pending. + This disables the example group defined by this behavior and ensures the code within is never run. +*/ +public func xitBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.xitBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} +/** + Use this to quickly focus a `describe` closure, focusing the examples in the closure. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the closure--they are all treated as focused. +*/ +public func fdescribe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus a `context` closure. Equivalent to `fdescribe`. +*/ +public func fcontext(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus an `it` closure, focusing the example. + If any examples in the test suite are focused, only those examples are executed. +*/ +public func fit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.fit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + fitBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.fitBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} + +/** + Use this to quickly focus on `itBehavesLike` closure. + */ +public func fitBehavesLike(_ behavior: Behavior.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) { + World.sharedWorld.fitBehavesLike(behavior, context: context, flags: flags, file: file, line: line) +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift b/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift new file mode 100644 index 0000000..942c2e6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift @@ -0,0 +1,210 @@ +import Foundation + +/** + Adds methods to World to support top-level DSL functions (Swift) and + macros (Objective-C). These functions map directly to the DSL that test + writers use in their specs. +*/ +extension World { + internal func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + internal func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } + + internal func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + registerSharedExample(name, closure: closure) + } + + internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'describe' cannot be used inside '\(currentPhase)', 'describe' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleGroup != nil else { + raiseError("Error: example group was not created by its parent QuickSpec spec. Check that describe() or context() was used in QuickSpec.spec() and not a more general context (i.e. an XCTestCase test)") + } + let group = ExampleGroup(description: description, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group, closure: closure) + } + + internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'context' cannot be used inside '\(currentPhase)', 'context' may only be used inside 'context' or 'describe'. ") + } + self.describe(description, flags: flags, closure: closure) + } + + internal func fdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.describe(description, flags: focusedFlags, closure: closure) + } + + internal func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.describe(description, flags: pendingFlags, closure: closure) + } + + internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'beforeEach' cannot be used inside '\(currentPhase)', 'beforeEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendBefore(closure) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(beforeEachWithMetadata:) + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#else + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#endif + + internal func afterEach(_ closure: @escaping AfterExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'afterEach' cannot be used inside '\(currentPhase)', 'afterEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendAfter(closure) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(afterEachWithMetadata:) + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#else + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#endif + + @nonobjc + internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + if beforesCurrentlyExecuting { + raiseError("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ") + } + if aftersCurrentlyExecuting { + raiseError("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleMetadata == nil else { + raiseError("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) + currentExampleGroup.appendExample(example) + } + + @nonobjc + internal func fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.it(description, flags: focusedFlags, file: file, line: line, closure: closure) + } + + @nonobjc + internal func xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.it(description, flags: pendingFlags, file: file, line: line, closure: closure) + } + + @nonobjc + internal func itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + guard currentExampleMetadata == nil else { + raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let closure = World.sharedWorld.sharedExample(name) + + let group = ExampleGroup(description: name, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group) { + closure(sharedExampleContext) + } + + group.walkDownExamples { (example: Example) in + example.isSharedExample = true + example.callsite = callsite + } + } + + @nonobjc + internal func fitBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: focusedFlags, file: file, line: line) + } + + internal func itBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + guard currentExampleMetadata == nil else { + raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let closure = behavior.spec + let group = ExampleGroup(description: behavior.name, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group) { + closure(context) + } + + group.walkDownExamples { (example: Example) in + example.isSharedExample = true + example.callsite = callsite + } + } + + internal func fitBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.itBehavesLike(behavior, context: context, flags: focusedFlags, file: file, line: line) + } + + internal func xitBehavesLike(_ behavior: Behavior.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.itBehavesLike(behavior, context: context, flags: pendingFlags, file: file, line: line) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objc(itWithDescription:flags:file:line:closure:) + internal func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + it(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(fitWithDescription:flags:file:line:closure:) + internal func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + fit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(xitWithDescription:flags:file:line:closure:) + internal func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + xit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:) + internal func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) + } +#endif + + internal func pending(_ description: String, closure: () -> Void) { + print("Pending: \(description)") + } + + private var currentPhase: String { + if beforesCurrentlyExecuting { + return "beforeEach" + } else if aftersCurrentlyExecuting { + return "afterEach" + } + + return "it" + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift b/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift new file mode 100644 index 0000000..155fefd --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +internal func raiseError(_ message: String) -> Never { +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise() +#endif + + // This won't be reached when ObjC is available and the exception above is raisd + fatalError(message) +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Example.swift b/Carthage/Checkouts/Quick/Sources/Quick/Example.swift new file mode 100644 index 0000000..cf7b4a3 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Example.swift @@ -0,0 +1,134 @@ +import Foundation + +private var numberOfExamplesRun = 0 +private var numberOfIncludedExamples = 0 + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _ExampleBase: NSObject {} + #else + public class _ExampleBase: NSObject {} + #endif +#else +public class _ExampleBase: NSObject {} +#endif + +/** + Examples, defined with the `it` function, use assertions to + demonstrate how code should behave. These are like "tests" in XCTest. +*/ +final public class Example: _ExampleBase { + /** + A boolean indicating whether the example is a shared example; + i.e.: whether it is an example defined with `itBehavesLike`. + */ + public var isSharedExample = false + + /** + The site at which the example is defined. + This must be set correctly in order for Xcode to highlight + the correct line in red when reporting a failure. + */ + public var callsite: Callsite + + weak internal var group: ExampleGroup? + + private let internalDescription: String + private let closure: () -> Void + private let flags: FilterFlags + + internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: @escaping () -> Void) { + self.internalDescription = description + self.closure = closure + self.callsite = callsite + self.flags = flags + } + + public override var description: String { + return internalDescription + } + + /** + The example name. A name is a concatenation of the name of + the example group the example belongs to, followed by the + description of the example itself. + + The example name is used to generate a test method selector + to be displayed in Xcode's test navigator. + */ + public var name: String { + guard let groupName = group?.name else { return description } + return "\(groupName), \(description)" + } + + /** + Executes the example closure, as well as all before and after + closures defined in the its surrounding example groups. + */ + public func run() { + let world = World.sharedWorld + + if numberOfIncludedExamples == 0 { + numberOfIncludedExamples = world.includedExampleCount + } + + if numberOfExamplesRun == 0 { + world.suiteHooks.executeBefores() + } + + let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun) + world.currentExampleMetadata = exampleMetadata + defer { + world.currentExampleMetadata = nil + } + + world.exampleHooks.executeBefores(exampleMetadata) + group!.phase = .beforesExecuting + for before in group!.befores { + before(exampleMetadata) + } + group!.phase = .beforesFinished + + closure() + + group!.phase = .aftersExecuting + for after in group!.afters { + after(exampleMetadata) + } + group!.phase = .aftersFinished + world.exampleHooks.executeAfters(exampleMetadata) + + numberOfExamplesRun += 1 + + if !world.isRunningAdditionalSuites && numberOfExamplesRun >= numberOfIncludedExamples { + world.suiteHooks.executeAfters() + } + } + + /** + Evaluates the filter flags set on this example and on the example groups + this example belongs to. Flags set on the example are trumped by flags on + the example group it belongs to. Flags on inner example groups are trumped + by flags on outer example groups. + */ + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + for (key, value) in group!.filterFlags { + aggregateFlags[key] = value + } + return aggregateFlags + } +} + +extension Example { + /** + Returns a boolean indicating whether two Example objects are equal. + If two examples are defined at the exact same callsite, they must be equal. + */ + @nonobjc public static func == (lhs: Example, rhs: Example) -> Bool { + return lhs.callsite == rhs.callsite + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift b/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift new file mode 100644 index 0000000..129bed0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift @@ -0,0 +1,99 @@ +import Foundation + +/** + Example groups are logical groupings of examples, defined with + the `describe` and `context` functions. Example groups can share + setup and teardown code. +*/ +final public class ExampleGroup: NSObject { + weak internal var parent: ExampleGroup? + internal let hooks = ExampleHooks() + + internal var phase: HooksPhase = .nothingExecuted + + private let internalDescription: String + private let flags: FilterFlags + private let isInternalRootExampleGroup: Bool + private var childGroups = [ExampleGroup]() + private var childExamples = [Example]() + + internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) { + self.internalDescription = description + self.flags = flags + self.isInternalRootExampleGroup = isInternalRootExampleGroup + } + + public override var description: String { + return internalDescription + } + + /** + Returns a list of examples that belong to this example group, + or to any of its descendant example groups. + */ + public var examples: [Example] { + return childExamples + childGroups.flatMap { $0.examples } + } + + internal var name: String? { + guard let parent = parent else { + return isInternalRootExampleGroup ? nil : description + } + + guard let name = parent.name else { return description } + return "\(name), \(description)" + } + + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + walkUp { group in + for (key, value) in group.flags { + aggregateFlags[key] = value + } + } + return aggregateFlags + } + + internal var befores: [BeforeExampleWithMetadataClosure] { + var closures = Array(hooks.befores.reversed()) + walkUp { group in + closures.append(contentsOf: Array(group.hooks.befores.reversed())) + } + return Array(closures.reversed()) + } + + internal var afters: [AfterExampleWithMetadataClosure] { + var closures = hooks.afters + walkUp { group in + closures.append(contentsOf: group.hooks.afters) + } + return closures + } + + internal func walkDownExamples(_ callback: (_ example: Example) -> Void) { + for example in childExamples { + callback(example) + } + for group in childGroups { + group.walkDownExamples(callback) + } + } + + internal func appendExampleGroup(_ group: ExampleGroup) { + group.parent = self + childGroups.append(group) + } + + internal func appendExample(_ example: Example) { + example.group = self + childExamples.append(example) + } + + private func walkUp(_ callback: (_ group: ExampleGroup) -> Void) { + var group = self + while let parent = group.parent { + callback(parent) + group = parent + } + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift b/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift new file mode 100644 index 0000000..3dd28ab --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift @@ -0,0 +1,37 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _ExampleMetadataBase: NSObject {} + #else + public class _ExampleMetadataBase: NSObject {} + #endif +#else +public class _ExampleMetadataBase: NSObject {} +#endif + +/** + A class that encapsulates information about an example, + including the index at which the example was executed, as + well as the example itself. +*/ +final public class ExampleMetadata: _ExampleMetadataBase { + /** + The example for which this metadata was collected. + */ + public let example: Example + + /** + The index at which this example was executed in the + test suite. + */ + public let exampleIndex: Int + + internal init(example: Example, exampleIndex: Int) { + self.example = example + self.exampleIndex = exampleIndex + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift b/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift new file mode 100644 index 0000000..da137f8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift @@ -0,0 +1,44 @@ +import Foundation + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + public class _FilterBase: NSObject {} + #else + public class _FilterBase: NSObject {} + #endif +#else +public class _FilterBase: NSObject {} +#endif + +/** + A mapping of string keys to booleans that can be used to + filter examples or example groups. For example, a "focused" + example would have the flags [Focused: true]. +*/ +public typealias FilterFlags = [String: Bool] + +/** + A namespace for filter flag keys, defined primarily to make the + keys available in Objective-C. +*/ +final public class Filter: _FilterBase { + /** + Example and example groups with [Focused: true] are included in test runs, + excluding all other examples without this flag. Use this to only run one or + two tests that you're currently focusing on. + */ + public class var focused: String { + return "focused" + } + + /** + Example and example groups with [Pending: true] are excluded from test runs. + Use this to temporarily suspend examples that you know do not pass yet. + */ + public class var pending: String { + return "pending" + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift new file mode 100644 index 0000000..9c7d310 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift @@ -0,0 +1,35 @@ +// MARK: Example Hooks + +/** + A closure executed before an example is run. +*/ +public typealias BeforeExampleClosure = () -> Void + +/** + A closure executed before an example is run. The closure is given example metadata, + which contains information about the example that is about to be run. +*/ +public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void + +/** + A closure executed after an example is run. +*/ +public typealias AfterExampleClosure = BeforeExampleClosure + +/** + A closure executed after an example is run. The closure is given example metadata, + which contains information about the example that has just finished running. +*/ +public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure + +// MARK: Suite Hooks + +/** + A closure executed before any examples are run. +*/ +public typealias BeforeSuiteClosure = () -> Void + +/** + A closure executed after all examples have finished running. +*/ +public typealias AfterSuiteClosure = BeforeSuiteClosure diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift new file mode 100644 index 0000000..449cbfc --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift @@ -0,0 +1,42 @@ +/** + A container for closures to be executed before and after each example. +*/ +final internal class ExampleHooks { + internal var befores: [BeforeExampleWithMetadataClosure] = [] + internal var afters: [AfterExampleWithMetadataClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) { + befores.append(closure) + } + + internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { + befores.append { (_: ExampleMetadata) in closure() } + } + + internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) { + afters.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterExampleClosure) { + afters.append { (_: ExampleMetadata) in closure() } + } + + internal func executeBefores(_ exampleMetadata: ExampleMetadata) { + phase = .beforesExecuting + for before in befores { + before(exampleMetadata) + } + + phase = .beforesFinished + } + + internal func executeAfters(_ exampleMetadata: ExampleMetadata) { + phase = .aftersExecuting + for after in afters { + after(exampleMetadata) + } + + phase = .aftersFinished + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift new file mode 100644 index 0000000..2440158 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift @@ -0,0 +1,11 @@ +/** + A description of the execution cycle of the current example with + respect to the hooks of that example. + */ +internal enum HooksPhase { + case nothingExecuted + case beforesExecuting + case beforesFinished + case aftersExecuting + case aftersFinished +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift new file mode 100644 index 0000000..b39292b --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift @@ -0,0 +1,32 @@ +/** + A container for closures to be executed before and after all examples. +*/ +final internal class SuiteHooks { + internal var befores: [BeforeSuiteClosure] = [] + internal var afters: [AfterSuiteClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) { + befores.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterSuiteClosure) { + afters.append(closure) + } + + internal func executeBefores() { + phase = .beforesExecuting + for before in befores { + before() + } + phase = .beforesFinished + } + + internal func executeAfters() { + phase = .aftersExecuting + for after in afters { + after() + } + phase = .aftersFinished + } +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/Info.plist b/Carthage/Checkouts/Quick/Sources/Quick/Info.plist new file mode 100644 index 0000000..9667430 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 - present, Quick Team. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift b/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift new file mode 100644 index 0000000..d7a1442 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift @@ -0,0 +1,25 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + +import Foundation + +extension Bundle { + + /** + Locates the first bundle with a '.xctest' file extension. + */ + internal static var currentTestBundle: Bundle? { + return allBundles.first { $0.bundlePath.hasSuffix(".xctest") } + } + + /** + Return the module name of the bundle. + Uses the bundle filename and transform it to match Xcode's transformation. + Module name has to be a valid "C99 extended identifier". + */ + internal var moduleName: String { + let fileName = bundleURL.fileName as NSString + return fileName.c99ExtendedIdentifier + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift b/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift new file mode 100644 index 0000000..8d67d8d --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift @@ -0,0 +1,49 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +extension NSString { + private static var invalidCharacters: CharacterSet = { + var invalidCharacters = CharacterSet() + + let invalidCharacterSets: [CharacterSet] = [ + .whitespacesAndNewlines, + .illegalCharacters, + .controlCharacters, + .punctuationCharacters, + .nonBaseCharacters, + .symbols + ] + + for invalidSet in invalidCharacterSets { + invalidCharacters.formUnion(invalidSet) + } + + return invalidCharacters + }() + + /// This API is not meant to be used outside Quick, so will be unavaialbe in + /// a next major version. + @objc(qck_c99ExtendedIdentifier) + public var c99ExtendedIdentifier: String { + let validComponents = components(separatedBy: NSString.invalidCharacters) + let result = validComponents.joined(separator: "_") + + return result.isEmpty ? "_" : result + } +} + +/// Extension methods or properties for NSObject subclasses are invisible from +/// the Objective-C runtime on static linking unless the consumers add `-ObjC` +/// linker flag, so let's make a wrapper class to mitigate that situation. +/// +/// See: https://github.com/Quick/Quick/issues/785 and https://github.com/Quick/Quick/pull/803 +@objc +class QCKObjCStringUtils: NSObject { + override private init() {} + + @objc + static func c99ExtendedIdentifier(from string: String) -> String { + return string.c99ExtendedIdentifier + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift b/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift new file mode 100644 index 0000000..eb9aba5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift @@ -0,0 +1,38 @@ +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE && os(Linux) + +/// When using Quick with swift-corelibs-xctest, automatic discovery of specs and +/// configurations is not available. Instead, you should create a standalone +/// executable and call this function from its main.swift file. This will execute +/// the specs and then terminate the process with an exit code of 0 if the tests +/// passed, or 1 if there were any failures. +/// +/// Quick is known to work with the DEVELOPMENT-SNAPSHOT-2016-02-08-a Swift toolchain. +/// +/// - parameter specs: An array of QuickSpec subclasses to run +/// - parameter configurations: An array QuickConfiguration subclasses for setting up +// global suite configuration (optional) +/// - parameter testCases: An array of XCTestCase test cases, just as would be passed +/// info `XCTMain` if you were using swift-corelibs-xctest directly. +/// This allows for mixing Quick specs and XCTestCase tests in one run. +public func QCKMain(_ specs: [QuickSpec.Type], + configurations: [QuickConfiguration.Type] = [], + testCases: [XCTestCaseEntry] = []) -> Never { + let world = World.sharedWorld + + // Perform all configurations (ensures that shared examples have been discovered) + world.configure { configuration in + for configurationClass in configurations { + configurationClass.configure(configuration) + } + } + world.finalizeConfiguration() + + XCTMain(specs.flatMap { testCase($0.allTests) } + testCases) +} + +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift b/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift new file mode 100644 index 0000000..415b680 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift @@ -0,0 +1,74 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +/** + Responsible for building a "Selected tests" suite. This corresponds to a single + spec, and all its examples. + */ +internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder { + + /** + The test spec class to run. + */ + let testCaseClass: AnyClass! + + /** + For Objective-C classes, returns the class name. For Swift classes without, + an explicit Objective-C name, returns a module-namespaced class name + (e.g., "FooTests.FooSpec"). + */ + var testSuiteClassName: String { + return NSStringFromClass(testCaseClass) + } + + /** + Given a test case name: + + FooSpec/testFoo + + Optionally constructs a test suite builder for the named test case class + in the running test bundle. + + If no test bundle can be found, or the test case class can't be found, + initialization fails and returns `nil`. + */ + init?(forTestCaseWithName name: String) { + guard let testCaseClass = testCaseClassForTestCaseWithName(name) else { + self.testCaseClass = nil + return nil + } + + self.testCaseClass = testCaseClass + } + + /** + Returns a `QuickTestSuite` that runs the associated test case class. + */ + func buildTestSuite() -> QuickTestSuite { + return QuickTestSuite(forTestCaseClass: testCaseClass) + } + +} + +/** + Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named + test case class in that bundle. + + Returns `nil` if a bundle or test case class cannot be found. + */ +private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? { + func extractClassName(_ name: String) -> String? { + return name.components(separatedBy: "/").first + } + + guard let className = extractClassName(name) else { return nil } + guard let bundle = Bundle.currentTestBundle else { return nil } + + if let testCaseClass = bundle.classNamed(className) { return testCaseClass } + + let moduleName = bundle.moduleName + + return NSClassFromString("\(moduleName).\(className)") +} + +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift b/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift new file mode 100644 index 0000000..12845d8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift @@ -0,0 +1,134 @@ +import XCTest + +// NOTE: This file is not intended to be included in the Xcode project or CocoaPods. +// It is picked up by the Swift Package Manager during its build process. + +#if SWIFT_PACKAGE + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +import QuickSpecBase + +public typealias QuickSpecBase = _QuickSpecBase +#else +public typealias QuickSpecBase = XCTestCase +#endif + +open class QuickSpec: QuickSpecBase { + open func spec() {} + +#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) + public required init() { + super.init(name: "", testClosure: { _ in }) + } + public required init(name: String, testClosure: @escaping (XCTestCase) throws -> Swift.Void) { + super.init(name: name, testClosure: testClosure) + } +#else + public required override init() { + super.init() + } + + /// This method is used as a hook for the following two purposes + /// + /// 1. Performing all configurations + /// 2. Gathering examples for each spec classes + /// + /// On Linux, those are done in `LinuxMain.swift` and `Quick.QCKMain`. But + /// SwiftPM on macOS does not have the mechanism (test cases are automatically + /// discovered powered by Objective-C runtime), so we needed the alternative + /// way. + #if swift(>=4) + override open class var defaultTestSuite: XCTestSuite { + configureDefaultTestSuite() + + return super.defaultTestSuite + } + #else + override open class func defaultTestSuite() -> XCTestSuite { + configureDefaultTestSuite() + + return super.defaultTestSuite() + } + #endif + + private static func configureDefaultTestSuite() { + let world = World.sharedWorld + + if !world.isConfigurationFinalized { + // Perform all configurations (ensures that shared examples have been discovered) + world.configure { configuration in + qck_enumerateSubclasses(QuickConfiguration.self) { configurationClass in + configurationClass.configure(configuration) + } + } + world.finalizeConfiguration() + } + + // Let's gather examples for each spec classes. This has the same effect + // as listing spec classes in `LinuxMain.swift` on Linux. + _ = allTests + } + + override open class func _qck_testMethodSelectors() -> [_QuickSelectorWrapper] { + let examples = World.sharedWorld.examples(self) + + var selectorNames = Set() + return examples.map { example in + let selector = addInstanceMethod(for: example, classSelectorNames: &selectorNames) + return _QuickSelectorWrapper(selector: selector) + } + } + + private static func addInstanceMethod(for example: Example, classSelectorNames selectorNames : inout Set) -> Selector { + let block: @convention(block) (QuickSpec) -> Void = { _ in + example.run() + } + let implementation = imp_implementationWithBlock(block as Any) + + let originalName = example.name + var selectorName = originalName + var i: UInt = 2 + + while selectorNames.contains(selectorName) { + selectorName = String(format: "%@_%tu", originalName, i) + i += 1 + } + + selectorNames.insert(selectorName) + + let selector = NSSelectorFromString(selectorName) + class_addMethod(self, selector, implementation, "v@:") + + return selector + } +#endif + + static var allTestsCache = [String: [(String, (XCTestCase) -> () throws -> Void)]]() + + public class var allTests: [(String, (XCTestCase) -> () throws -> Void)] { + if let cached = allTestsCache[String(describing: self)] { + return cached + } + + gatherExamplesIfNeeded() + + let examples = World.sharedWorld.examples(self) + let result = examples.map { example -> (String, (XCTestCase) -> () throws -> Void) in + return (example.name, { _ in { example.run() } }) + } + allTestsCache[String(describing: self)] = result + return result + } + + internal static func gatherExamplesIfNeeded() { + let world = World.sharedWorld + let rootExampleGroup = world.rootExampleGroupForSpecClass(self) + if rootExampleGroup.examples.isEmpty { + world.currentExampleGroup = rootExampleGroup + self.init().spec() + world.currentExampleGroup = nil + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift b/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift new file mode 100644 index 0000000..0fe76a7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift @@ -0,0 +1,52 @@ +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + +import XCTest + +/** + This protocol defines the role of an object that builds test suites. + */ +internal protocol QuickTestSuiteBuilder { + + /** + Construct a `QuickTestSuite` instance with the appropriate test cases added as tests. + + Subsequent calls to this method should return equivalent test suites. + */ + func buildTestSuite() -> QuickTestSuite + +} + +/** + A base class for a class cluster of Quick test suites, that should correctly + build dynamic test suites for XCTest to execute. + */ +public class QuickTestSuite: XCTestSuite { + + private static var builtTestSuites: Set = Set() + + /** + Construct a test suite for a specific, selected subset of test cases (rather + than the default, which as all test cases). + + If this method is called multiple times for the same test case class, e.g.. + + FooSpec/testFoo + FooSpec/testBar + + It is expected that the first call should return a valid test suite, and + all subsequent calls should return `nil`. + */ + @objc + public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { + guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } + + let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName) + if inserted { + return builder.buildTestSuite() + } else { + return nil + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift b/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift new file mode 100644 index 0000000..23c4781 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift @@ -0,0 +1,12 @@ +import Foundation + +extension URL { + + /** + Returns the path file name without file extension. + */ + var fileName: String { + return self.deletingPathExtension().lastPathComponent + } + +} diff --git a/Carthage/Checkouts/Quick/Sources/Quick/World.swift b/Carthage/Checkouts/Quick/Sources/Quick/World.swift new file mode 100644 index 0000000..59ea7e6 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/Quick/World.swift @@ -0,0 +1,247 @@ +import Foundation + +/** + A closure that, when evaluated, returns a dictionary of key-value + pairs that can be accessed from within a group of shared examples. +*/ +public typealias SharedExampleContext = () -> [String: Any] + +/** + A closure that is used to define a group of shared examples. This + closure may contain any number of example and example groups. +*/ +public typealias SharedExampleClosure = (@escaping SharedExampleContext) -> Void + +// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE` +// does not work as expected. +#if swift(>=3.2) + #if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + @objcMembers + internal class _WorldBase: NSObject {} + #else + internal class _WorldBase: NSObject {} + #endif +#else +internal class _WorldBase: NSObject {} +#endif + +/** + A collection of state Quick builds up in order to work its magic. + World is primarily responsible for maintaining a mapping of QuickSpec + classes to root example groups for those classes. + + It also maintains a mapping of shared example names to shared + example closures. + + You may configure how Quick behaves by calling the -[World configure:] + method from within an overridden +[QuickConfiguration configure:] method. +*/ +final internal class World: _WorldBase { + /** + The example group that is currently being run. + The DSL requires that this group is correctly set in order to build a + correct hierarchy of example groups and their examples. + */ + internal var currentExampleGroup: ExampleGroup! + + /** + The example metadata of the test that is currently being run. + This is useful for using the Quick test metadata (like its name) at + runtime. + */ + + internal var currentExampleMetadata: ExampleMetadata? + + /** + A flag that indicates whether additional test suites are being run + within this test suite. This is only true within the context of Quick + functional tests. + */ +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + // Convention of generating Objective-C selector has been changed on Swift 3 + @objc(isRunningAdditionalSuites) + internal var isRunningAdditionalSuites = false +#else + internal var isRunningAdditionalSuites = false +#endif + + private var specs: [String: ExampleGroup] = [:] + private var sharedExamples: [String: SharedExampleClosure] = [:] + private let configuration = Configuration() + + internal private(set) var isConfigurationFinalized = false + + internal var exampleHooks: ExampleHooks {return configuration.exampleHooks } + internal var suiteHooks: SuiteHooks { return configuration.suiteHooks } + + // MARK: Singleton Constructor + + private override init() {} + + static let sharedWorld = World() + + // MARK: Public Interface + + /** + Exposes the World's Configuration object within the scope of the closure + so that it may be configured. This method must not be called outside of + an overridden +[QuickConfiguration configure:] method. + + - parameter closure: A closure that takes a Configuration object that can + be mutated to change Quick's behavior. + */ + internal func configure(_ closure: QuickConfigurer) { + assert(!isConfigurationFinalized, + "Quick cannot be configured outside of a +[QuickConfiguration configure:] method. You should not call -[World configure:] directly. Instead, subclass QuickConfiguration and override the +[QuickConfiguration configure:] method.") + closure(configuration) + } + + /** + Finalizes the World's configuration. + Any subsequent calls to World.configure() will raise. + */ + internal func finalizeConfiguration() { + isConfigurationFinalized = true + } + + /** + Returns an internally constructed root example group for the given + QuickSpec class. + + A root example group with the description "root example group" is lazily + initialized for each QuickSpec class. This root example group wraps the + top level of a -[QuickSpec spec] method--it's thanks to this group that + users can define beforeEach and it closures at the top level, like so: + + override func spec() { + // These belong to the root example group + beforeEach {} + it("is at the top level") {} + } + + - parameter cls: The QuickSpec class for which to retrieve the root example group. + - returns: The root example group for the class. + */ + internal func rootExampleGroupForSpecClass(_ cls: AnyClass) -> ExampleGroup { + let name = String(describing: cls) + + if let group = specs[name] { + return group + } else { + let group = ExampleGroup( + description: "root example group", + flags: [:], + isInternalRootExampleGroup: true + ) + specs[name] = group + return group + } + } + + /** + Returns all examples that should be run for a given spec class. + There are two filtering passes that occur when determining which examples should be run. + That is, these examples are the ones that are included by inclusion filters, and are + not excluded by exclusion filters. + + - parameter specClass: The QuickSpec subclass for which examples are to be returned. + - returns: A list of examples to be run as test invocations. + */ + internal func examples(_ specClass: AnyClass) -> [Example] { + // 1. Grab all included examples. + let included = includedExamples + // 2. Grab the intersection of (a) examples for this spec, and (b) included examples. + let spec = rootExampleGroupForSpecClass(specClass).examples.filter { included.contains($0) } + // 3. Remove all excluded examples. + return spec.filter { example in + !self.configuration.exclusionFilters.reduce(false) { $0 || $1(example) } + } + } + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @objc(examplesForSpecClass:) + internal func objc_examples(_ specClass: AnyClass) -> [Example] { + return examples(specClass) + } +#endif + + // MARK: Internal + + internal func registerSharedExample(_ name: String, closure: @escaping SharedExampleClosure) { + raiseIfSharedExampleAlreadyRegistered(name) + sharedExamples[name] = closure + } + + internal func sharedExample(_ name: String) -> SharedExampleClosure { + raiseIfSharedExampleNotRegistered(name) + return sharedExamples[name]! + } + + internal var includedExampleCount: Int { + return includedExamples.count + } + + internal var beforesCurrentlyExecuting: Bool { + let suiteBeforesExecuting = suiteHooks.phase == .beforesExecuting + let exampleBeforesExecuting = exampleHooks.phase == .beforesExecuting + var groupBeforesExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupBeforesExecuting = runningExampleGroup.phase == .beforesExecuting + } + + return suiteBeforesExecuting || exampleBeforesExecuting || groupBeforesExecuting + } + + internal var aftersCurrentlyExecuting: Bool { + let suiteAftersExecuting = suiteHooks.phase == .aftersExecuting + let exampleAftersExecuting = exampleHooks.phase == .aftersExecuting + var groupAftersExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupAftersExecuting = runningExampleGroup.phase == .aftersExecuting + } + + return suiteAftersExecuting || exampleAftersExecuting || groupAftersExecuting + } + + internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { + let previousExampleGroup = currentExampleGroup + currentExampleGroup = group + + closure() + + currentExampleGroup = previousExampleGroup + } + + private var allExamples: [Example] { + var all: [Example] = [] + for (_, group) in specs { + group.walkDownExamples { all.append($0) } + } + return all + } + + private var includedExamples: [Example] { + let all = allExamples + let included = all.filter { example in + return self.configuration.inclusionFilters.reduce(false) { $0 || $1(example) } + } + + if included.isEmpty && configuration.runAllWhenEverythingFiltered { + return all + } else { + return included + } + } + + private func raiseIfSharedExampleAlreadyRegistered(_ name: String) { + if sharedExamples[name] != nil { + raiseError("A shared example named '\(name)' has already been registered.") + } + } + + private func raiseIfSharedExampleNotRegistered(_ name: String) { + if sharedExamples[name] == nil { + raiseError("No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(sharedExamples.keys))'") + } + } +} diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h new file mode 100644 index 0000000..5646199 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h @@ -0,0 +1,30 @@ +#import + +@class Configuration; + +/** + Subclass QuickConfiguration and override the +[QuickConfiguration configure:] + method in order to configure how Quick behaves when running specs, or to define + shared examples that are used across spec files. + */ +@interface QuickConfiguration : NSObject + +/** + This method is executed on each subclass of this class before Quick runs + any examples. You may override this method on as many subclasses as you like, but + there is no guarantee as to the order in which these methods are executed. + + You can override this method in order to: + + 1. Configure how Quick behaves, by modifying properties on the Configuration object. + Setting the same properties in several methods has undefined behavior. + + 2. Define shared examples using `sharedExamples`. + + @param configuration A mutable object that is used to configure how Quick behaves on + a framework level. For details on all the options, see the + documentation in Configuration.swift. + */ ++ (void)configure:(Configuration *)configuration; + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m new file mode 100644 index 0000000..17beaa7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m @@ -0,0 +1,88 @@ +#import "QuickConfiguration.h" +#import + +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +typedef void (^QCKClassEnumerationBlock)(Class klass); + +/** + Finds all direct subclasses of the given class and passes them to the block provided. + The classes are iterated over in the order that objc_getClassList returns them. + + @param klass The base class to find subclasses of. + @param block A block that takes a Class. This block will be executed once for each subclass of klass. + */ +void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) { + Class *classes = NULL; + int classesCount = objc_getClassList(NULL, 0); + + if (classesCount > 0) { + classes = (Class *)calloc(sizeof(Class), classesCount); + classesCount = objc_getClassList(classes, classesCount); + + Class subclass, superclass; + for(int i = 0; i < classesCount; i++) { + subclass = classes[i]; + superclass = class_getSuperclass(subclass); + if (superclass == klass && block) { + block(subclass); + } + } + + free(classes); + } +} + +@implementation QuickConfiguration + +#pragma mark - Object Lifecycle + +/** + QuickConfiguration is not meant to be instantiated; it merely provides a hook + for users to configure how Quick behaves. Raise an exception if an instance of + QuickConfiguration is created. + */ +- (instancetype)init { + NSString *className = NSStringFromClass([self class]); + NSString *selectorName = NSStringFromSelector(@selector(configure:)); + [NSException raise:NSInternalInconsistencyException + format:@"%@ is not meant to be instantiated; " + @"subclass %@ and override %@ to configure Quick.", + className, className, selectorName]; + return nil; +} + +#pragma mark - NSObject Overrides + +/** + Hook into when QuickConfiguration is initialized in the runtime in order to + call +[QuickConfiguration configure:] on each of its subclasses. + */ ++ (void)initialize { + // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. + if ([self class] == [QuickConfiguration class]) { + + // Only enumerate over subclasses once, even if +[QuickConfiguration initialize] + // were to be called several times. This is necessary because +[QuickSpec initialize] + // manually calls +[QuickConfiguration initialize]. + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) { + [[World sharedWorld] configure:^(Configuration *configuration) { + [klass configure:configuration]; + }]; + }); + [[World sharedWorld] finalizeConfiguration]; + }); + } +} + +#pragma mark - Public Interface + ++ (void)configure:(Configuration *)configuration { } + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h new file mode 100644 index 0000000..c5f3152 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h @@ -0,0 +1,234 @@ +#import + +@class ExampleMetadata; + +/** + Provides a hook for Quick to be configured before any examples are run. + Within this scope, override the +[QuickConfiguration configure:] method + to set properties on a configuration object to customize Quick behavior. + For details, see the documentation for Configuraiton.swift. + + @param name The name of the configuration class. Like any Objective-C + class name, this must be unique to the current runtime + environment. + */ +#define QuickConfigurationBegin(name) \ + @interface name : QuickConfiguration; @end \ + @implementation name \ + + +/** + Marks the end of a Quick configuration. + Make sure you put this after `QuickConfigurationBegin`. + */ +#define QuickConfigurationEnd \ + @end \ + + +/** + Defines a new QuickSpec. Define examples and example groups within the space + between this and `QuickSpecEnd`. + + @param name The name of the spec class. Like any Objective-C class name, this + must be unique to the current runtime environment. + */ +#define QuickSpecBegin(name) \ + @interface name : QuickSpec; @end \ + @implementation name \ + - (void)spec { \ + + +/** + Marks the end of a QuickSpec. Make sure you put this after `QuickSpecBegin`. + */ +#define QuickSpecEnd \ + } \ + @end \ + +typedef NSDictionary *(^QCKDSLSharedExampleContext)(void); +typedef void (^QCKDSLSharedExampleBlock)(QCKDSLSharedExampleContext); +typedef void (^QCKDSLEmptyBlock)(void); +typedef void (^QCKDSLExampleMetadataBlock)(ExampleMetadata *exampleMetadata); + +#define QUICK_EXPORT FOUNDATION_EXPORT + +QUICK_EXPORT void qck_beforeSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure); +QUICK_EXPORT void qck_describe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_context(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_afterEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_pending(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure); + +#ifndef QUICK_DISABLE_SHORT_SYNTAX +/** + Defines a closure to be run prior to any examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before the first example is run, this closure + will not be executed. + + @param closure The closure to be run prior to any examples in the test suite. + */ +static inline void beforeSuite(QCKDSLEmptyBlock closure) { + qck_beforeSuite(closure); +} + + +/** + Defines a closure to be run after all of the examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before all examples are run, this closure + will not be executed. + + @param closure The closure to be run after all of the examples in the test suite. + */ +static inline void afterSuite(QCKDSLEmptyBlock closure) { + qck_afterSuite(closure); +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + @param name The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + @param closure A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + */ +static inline void sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + qck_sharedExamples(name, closure); +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + @param description An arbitrary string describing the example group. + @param closure A closure that can contain other examples. + */ +static inline void describe(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +/** + Defines an example group. Equivalent to `describe`. + */ +static inline void context(NSString *description, QCKDSLEmptyBlock closure) { + qck_context(description, closure); +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run prior to each example. + */ +static inline void beforeEach(QCKDSLEmptyBlock closure) { + qck_beforeEach(closure); +} + +/** + Identical to QCKDSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. + */ +static inline void beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_beforeEachWithMetadata(closure); +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run after each example. + */ +static inline void afterEach(QCKDSLEmptyBlock closure) { + qck_afterEach(closure); +} + +/** + Identical to QCKDSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. + */ +static inline void afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_afterEachWithMetadata(closure); +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + @param description An arbitrary string describing the example or example group. + @param closure A closure that will not be evaluated. + */ +static inline void pending(NSString *description, QCKDSLEmptyBlock closure) { + qck_pending(description, closure); +} + +/** + Use this to quickly mark a `describe` block as pending. + This disables all examples within the block. + */ +static inline void xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +/** + Use this to quickly mark a `context` block as pending. + This disables all examples within the block. + */ +static inline void xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xcontext(description, closure); +} + +/** + Use this to quickly focus a `describe` block, focusing the examples in the block. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the block--they are all treated as focused. + */ +static inline void fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} + +/** + Use this to quickly focus a `context` block. Equivalent to `fdescribe`. + */ +static inline void fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fcontext(description, closure); +} + +#define it qck_it +#define xit qck_xit +#define fit qck_fit +#define itBehavesLike qck_itBehavesLike +#define xitBehavesLike qck_xitBehavesLike +#define fitBehavesLike qck_fitBehavesLike +#endif + +#define qck_it qck_it_builder(@{}, @(__FILE__), __LINE__) +#define qck_xit qck_it_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fit qck_it_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) +#define qck_itBehavesLike qck_itBehavesLike_builder(@{}, @(__FILE__), __LINE__) +#define qck_xitBehavesLike qck_itBehavesLike_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fitBehavesLike qck_itBehavesLike_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) + +typedef void (^QCKItBlock)(NSString *description, QCKDSLEmptyBlock closure); +typedef void (^QCKItBehavesLikeBlock)(NSString *description, QCKDSLSharedExampleContext context); + +QUICK_EXPORT QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line); +QUICK_EXPORT QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line); diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m new file mode 100644 index 0000000..624832e --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m @@ -0,0 +1,83 @@ +#import "QCKDSL.h" + +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +void qck_beforeSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeSuite:closure]; +} + +void qck_afterSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterSuite:closure]; +} + +void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + [[World sharedWorld] sharedExamples:name closure:closure]; +} + +void qck_describe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] describe:description flags:@{} closure:closure]; +} + +void qck_context(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +void qck_beforeEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeEach:closure]; +} + +void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] beforeEachWithMetadata:closure]; +} + +void qck_afterEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterEach:closure]; +} + +void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] afterEachWithMetadata:closure]; +} + +QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] itWithDescription:description + flags:flags + file:file + line:line + closure:closure]; + }; +} + +QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *name, QCKDSLSharedExampleContext context) { + [[World sharedWorld] itBehavesLikeSharedExampleNamed:name + sharedExampleContext:context + flags:flags + file:file + line:line]; + }; +} + +void qck_pending(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] pending:description closure:closure]; +} + +void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] xdescribe:description flags:@{} closure:closure]; +} + +void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] fdescribe:description flags:@{} closure:closure]; +} + +void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h new file mode 100644 index 0000000..87dad10 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h @@ -0,0 +1,11 @@ +#import + +//! Project version number for Quick. +FOUNDATION_EXPORT double QuickVersionNumber; + +//! Project version string for Quick. +FOUNDATION_EXPORT const unsigned char QuickVersionString[]; + +#import "QuickSpec.h" +#import "QCKDSL.h" +#import "QuickConfiguration.h" diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h new file mode 100644 index 0000000..21bc772 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h @@ -0,0 +1,56 @@ +#import + +/** + QuickSpec is a base class all specs written in Quick inherit from. + They need to inherit from QuickSpec, a subclass of XCTestCase, in + order to be discovered by the XCTest framework. + + XCTest automatically compiles a list of XCTestCase subclasses included + in the test target. It iterates over each class in that list, and creates + a new instance of that class for each test method. It then creates an + "invocation" to execute that test method. The invocation is an instance of + NSInvocation, which represents a single message send in Objective-C. + The invocation is set on the XCTestCase instance, and the test is run. + + Most of the code in QuickSpec is dedicated to hooking into XCTest events. + First, when the spec is first loaded and before it is sent any messages, + the +[NSObject initialize] method is called. QuickSpec overrides this method + to call +[QuickSpec spec]. This builds the example group stacks and + registers them with Quick.World, a global register of examples. + + Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest + automatically finds all methods whose selectors begin with the string "test". + However, QuickSpec overrides this default behavior by implementing the + +[XCTestCase testInvocations] method. This method iterates over each example + registered in Quick.World, defines a new method for that example, and + returns an invocation to call that method to XCTest. Those invocations are + the tests that are run by XCTest. Their selector names are displayed in + the Xcode test navigation bar. + */ +@interface QuickSpec : XCTestCase + +/** + Override this method in your spec to define a set of example groups + and examples. + + @code + override func spec() { + describe("winter") { + it("is coming") { + // ... + } + } + } + @endcode + + See DSL.swift for more information on what syntax is available. + */ +- (void)spec; + +/** + Returns the currently executing spec. Use in specs that require XCTestCase + methds, e.g. expectationWithDescription. +*/ +@property (class, nonatomic, readonly) QuickSpec *current; + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m new file mode 100644 index 0000000..ed70d35 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m @@ -0,0 +1,149 @@ +#import "QuickSpec.h" +#import "QuickConfiguration.h" + +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +static QuickSpec *currentSpec = nil; + +@interface QuickSpec () +@property (nonatomic, strong) Example *example; +@end + +@implementation QuickSpec + +#pragma mark - XCTestCase Overrides + +/** + The runtime sends initialize to each class in a program just before the class, or any class + that inherits from it, is sent its first message from within the program. QuickSpec hooks into + this event to compile the example groups for this spec subclass. + + If an exception occurs when compiling the examples, report it to the user. Chances are they + included an expectation outside of a "it", "describe", or "context" block. + */ ++ (void)initialize { + [QuickConfiguration initialize]; + + World *world = [World sharedWorld]; + [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ + QuickSpec *spec = [self new]; + + @try { + [spec spec]; + } + @catch (NSException *exception) { + [NSException raise:NSInternalInconsistencyException + format:@"An exception occurred when building Quick's example groups.\n" + @"Some possible reasons this might happen include:\n\n" + @"- An 'expect(...).to' expectation was evaluated outside of " + @"an 'it', 'context', or 'describe' block\n" + @"- 'sharedExamples' was called twice with the same name\n" + @"- 'itBehavesLike' was called with a name that is not registered as a shared example\n\n" + @"Here's the original exception: '%@', reason: '%@', userInfo: '%@'", + exception.name, exception.reason, exception.userInfo]; + } + [self testInvocations]; + }]; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; + + NSMutableSet *selectorNames = [NSMutableSet set]; + + for (Example *example in examples) { + SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; + + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + +#pragma mark - Public Interface + +- (void)spec { } + ++ (QuickSpec*) current { + return currentSpec; +} + +#pragma mark - Internal Methods + +/** + QuickSpec uses this method to dynamically define a new instance method for the + given example. The instance method runs the example, catching any exceptions. + The exceptions are then reported as test failures. + + In order to report the correct file and line number, examples must raise exceptions + containing following keys in their userInfo: + + - "SenTestFilenameKey": A String representing the file name + - "SenTestLineNumberKey": An Int representing the line number + + These keys used to be used by SenTestingKit, and are still used by some testing tools + in the wild. See: https://github.com/Quick/Quick/pull/41 + + @return The selector of the newly defined instance method. + */ ++ (SEL)addInstanceMethodForExample:(Example *)example classSelectorNames:(NSMutableSet *)selectorNames { + IMP implementation = imp_implementationWithBlock(^(QuickSpec *self){ + self.example = example; + currentSpec = self; + [example run]; + }); + + const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(void), @encode(id), @encode(SEL)] UTF8String]; + + NSString *originalName = [QCKObjCStringUtils c99ExtendedIdentifierFrom:example.name]; + NSString *selectorName = originalName; + NSUInteger i = 2; + + while ([selectorNames containsObject:selectorName]) { + selectorName = [NSString stringWithFormat:@"%@_%tu", originalName, i++]; + } + + [selectorNames addObject:selectorName]; + + SEL selector = NSSelectorFromString(selectorName); + class_addMethod(self, selector, implementation, types); + + return selector; +} + +/** + This method is used to record failures, whether they represent example + expectations that were not met, or exceptions raised during test setup + and teardown. By default, the failure will be reported as an + XCTest failure, and the example will be highlighted in Xcode. + */ +- (void)recordFailureWithDescription:(NSString *)description + inFile:(NSString *)filePath + atLine:(NSUInteger)lineNumber + expected:(BOOL)expected { + if (self.example.isSharedExample) { + filePath = self.example.callsite.file; + lineNumber = self.example.callsite.line; + } + [currentSpec.testRun recordFailureWithDescription:description + inFile:filePath + atLine:lineNumber + expected:expected]; +} + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m new file mode 100644 index 0000000..ae63036 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m @@ -0,0 +1,45 @@ +#import +#import + +#if __has_include("Quick-Swift.h") +#import "Quick-Swift.h" +#else +#import +#endif + +@interface XCTestSuite (QuickTestSuiteBuilder) +@end + +@implementation XCTestSuite (QuickTestSuiteBuilder) + +/** + In order to ensure we can correctly build dynamic test suites, we need to + replace some of the default test suite constructors. + */ ++ (void)load { + Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:)); + Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:)); + method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName); +} + +/** + The `+testSuiteForTestCaseWithName:` method is called when a specific test case + class is run from the Xcode test navigator. If the built test suite is `nil`, + Xcode will not run any tests for that test case. + + Given if the following test case class is run from the Xcode test navigator: + + FooSpec + testFoo + testBar + + XCTest will invoke this once per test case, with test case names following this format: + + FooSpec/testFoo + FooSpec/testBar + */ ++ (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name { + return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name]; +} + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m b/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m new file mode 100644 index 0000000..10b6f7e --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m @@ -0,0 +1,55 @@ +#import "QuickSpecBase.h" + +#pragma mark - _QuickSelectorWrapper + +@interface _QuickSelectorWrapper () +@property(nonatomic, assign) SEL selector; +@end + +@implementation _QuickSelectorWrapper + +- (instancetype)initWithSelector:(SEL)selector { + self = [super init]; + _selector = selector; + return self; +} + +@end + + +#pragma mark - _QuickSpecBase + +@implementation _QuickSpecBase + +- (instancetype)init { + self = [super initWithInvocation: nil]; + return self; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:wrappers.count]; + + for (_QuickSelectorWrapper *wrapper in wrappers) { + SEL selector = wrapper.selector; + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors { + return @[]; +} + +@end diff --git a/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h b/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h new file mode 100644 index 0000000..8881ca0 --- /dev/null +++ b/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h @@ -0,0 +1,11 @@ +#import +#import + +@interface _QuickSelectorWrapper : NSObject +- (instancetype)initWithSelector:(SEL)selector; +@end + +@interface _QuickSpecBase : XCTestCase ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors; +- (instancetype)init NS_DESIGNATED_INITIALIZER; +@end diff --git a/Carthage/Checkouts/Quick/Tests/LinuxMain.swift b/Carthage/Checkouts/Quick/Tests/LinuxMain.swift new file mode 100644 index 0000000..2a67c4a --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/LinuxMain.swift @@ -0,0 +1,45 @@ +import XCTest +import Quick + +@testable import QuickTests + +Quick.QCKMain([ + FunctionalTests_AfterEachSpec.self, + AfterSuiteTests.self, + FunctionalTests_BeforeEachSpec.self, + FunctionalTests_BeforeSuite_BeforeSuiteSpec.self, + FunctionalTests_BeforeSuite_Spec.self, + FunctionalTests_ItSpec.self, + FunctionalTests_PendingSpec.self, + FunctionalTests_SharedExamples_BeforeEachSpec.self, + FunctionalTests_SharedExamples_Spec.self, + FunctionalTests_SharedExamples_ContextSpec.self, + Configuration_AfterEachSpec.self, + Configuration_BeforeEachSpec.self, + FunctionalTests_CrossReferencingSpecA.self, + FunctionalTests_CrossReferencingSpecB.self, + _FunctionalTests_FocusedSpec_Focused.self, + _FunctionalTests_FocusedSpec_Unfocused.self +], +configurations: [ + FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples.self, + FunctionalTests_SharedExamplesTests_SharedExamples.self, + FunctionalTests_Configuration_AfterEach.self, + FunctionalTests_Configuration_BeforeEach.self, + FunctionalTests_FocusedSpec_SharedExamplesConfiguration.self +], +testCases: [ + testCase(AfterEachTests.allTests), + testCase(BeforeEachTests.allTests), + testCase(BeforeSuiteTests.allTests), + // testCase(DescribeTests.allTests), + testCase(ItTests.allTests), + testCase(PendingTests.allTests), + testCase(SharedExamples_BeforeEachTests.allTests), + testCase(SharedExamplesTests.allTests), + testCase(Configuration_AfterEachTests.allTests), + testCase(Configuration_BeforeEachTests.allTests), + testCase(FocusedTests.allTests), + testCase(FunctionalTests_CrossReferencingSpecA.allTests), + testCase(FunctionalTests_CrossReferencingSpecB.allTests) +]) diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m new file mode 100644 index 0000000..cd3522d --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m @@ -0,0 +1,32 @@ +@import XCTest; +@import Quick; +@import Nimble; + +static BOOL afterSuiteFirstTestExecuted = NO; +static BOOL afterSuiteTestsWasExecuted = NO; + +@interface AfterSuiteTests_ObjC : QuickSpec + +@end + +@implementation AfterSuiteTests_ObjC + +- (void)spec { + it(@"is executed before afterSuite", ^{ + expect(@(afterSuiteTestsWasExecuted)).to(beFalsy()); + }); + + afterSuite(^{ + afterSuiteTestsWasExecuted = YES; + }); +} + ++ (void)tearDown { + if (afterSuiteFirstTestExecuted) { + assert(afterSuiteTestsWasExecuted); + } else { + afterSuiteFirstTestExecuted = true; + } +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift new file mode 100644 index 0000000..ea4fc3e --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift @@ -0,0 +1,26 @@ +import XCTest +import Quick +import Nimble + +var afterSuiteFirstTestExecuted = false +var afterSuiteTestsWasExecuted = false + +class AfterSuiteTests: QuickSpec { + override func spec() { + afterSuite { + afterSuiteTestsWasExecuted = true + } + + it("is executed before afterSuite") { + expect(afterSuiteTestsWasExecuted).to(beFalsy()) + } + } + + override class func tearDown() { + if afterSuiteFirstTestExecuted { + assert(afterSuiteTestsWasExecuted, "afterSuiteTestsWasExecuted needs to be true") + } else { + afterSuiteFirstTestExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m new file mode 100644 index 0000000..5069f2b --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m @@ -0,0 +1,56 @@ +@import Quick; +@import Nimble; +@import XCTest; + +#import "QCKSpecRunner.h" + +QuickConfigurationBegin(FunctionalTests_SharedExamplesConfiguration_ObjC) + ++ (void)configure:(Configuration *)configuration { + sharedExamples(@"two passing shared examples (Objective-C)", ^(QCKDSLSharedExampleContext exampleContext) { + it(@"has an example that passes (4)", ^{}); + it(@"has another example that passes (5)", ^{}); + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(FunctionalTests_FocusedSpec_Focused_ObjC) + +it(@"has an unfocused example that fails, but is never run", ^{ XCTFail(); }); +fit(@"has a focused example that passes (1)", ^{}); + +fdescribe(@"a focused example group", ^{ + it(@"has an example that is not focused, but will be run, and passes (2)", ^{}); + fit(@"has a focused example that passes (3)", ^{}); +}); + +fitBehavesLike(@"two passing shared examples (Objective-C)", ^NSDictionary *{ return @{}; }); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_FocusedSpec_Unfocused_ObjC) + +it(@"has an unfocused example thay fails, but is never run", ^{ XCTFail(); }); + +describe(@"an unfocused example group that is never run", ^{ + beforeEach(^{ [NSException raise:NSInternalInconsistencyException format:@""]; }); + it(@"has an example that fails, but is never run", ^{ XCTFail(); }); +}); + +QuickSpecEnd + +@interface FocusedTests_ObjC: XCTestCase +@end + +@implementation FocusedTests_ObjC + +- (void)testOnlyFocusedExamplesAreExecuted { + XCTestRun *result = qck_runSpecs(@[ + [FunctionalTests_FocusedSpec_Focused_ObjC class], + [FunctionalTests_FocusedSpec_Unfocused_ObjC class] + ]); + XCTAssertEqual(result.executionCount, 5); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift new file mode 100644 index 0000000..132b748 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift @@ -0,0 +1,68 @@ +import Quick +import Nimble +import XCTest + +class FunctionalTests_FocusedSpec_SharedExamplesConfiguration: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("two passing shared examples") { + it("has an example that passes (4)") {} + it("has another example that passes (5)") {} + } + } +} + +class FunctionalTests_FocusedSpec_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("pass once") { expect(true).to(beTruthy()) } + it("pass twice") { expect(true).to(beTruthy()) } + it("pass three times") { expect(true).to(beTruthy()) } + } +} + +// The following `QuickSpec`s will be run in a same test suite with other specs +// on SwiftPM. We must avoid that the focused flags below affect other specs, so +// the examples of the two specs must be gathered lastly. That is the reason why +// the two specs have underscore prefix (and are listed at the bottom of `QCKMain`s +// `specs` array). + +class _FunctionalTests_FocusedSpec_Focused: QuickSpec { + override func spec() { + it("has an unfocused example that fails, but is never run") { fail() } + fit("has a focused example that passes (1)") {} + + fdescribe("a focused example group") { + it("has an example that is not focused, but will be run, and passes (2)") {} + fit("has a focused example that passes (3)") {} + } + + fitBehavesLike("two passing shared examples") + fitBehavesLike(FunctionalTests_FocusedSpec_Behavior.self) { () -> Void in } + } +} + +class _FunctionalTests_FocusedSpec_Unfocused: QuickSpec { + override func spec() { + it("has an unfocused example that fails, but is never run") { fail() } + + describe("an unfocused example group that is never run") { + beforeEach { assert(false) } + it("has an example that fails, but is never run") { fail() } + } + } +} + +final class FocusedTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (FocusedTests) -> () throws -> Void)] { + return [ + ("testOnlyFocusedExamplesAreExecuted", testOnlyFocusedExamplesAreExecuted) + ] + } + + func testOnlyFocusedExamplesAreExecuted() { + let result = qck_runSpecs([ + _FunctionalTests_FocusedSpec_Focused.self, + _FunctionalTests_FocusedSpec_Unfocused.self + ]) + XCTAssertEqual(result?.executionCount, 8) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift new file mode 100644 index 0000000..66dec1b --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift @@ -0,0 +1,30 @@ +@testable import Quick +import Nimble + +@discardableResult +public func qck_runSpec(_ specClass: QuickSpec.Type) -> TestRun? { + return qck_runSpecs([specClass]) +} + +@discardableResult +public func qck_runSpecs(_ specClasses: [QuickSpec.Type]) -> TestRun? { + Quick.World.sharedWorld.isRunningAdditionalSuites = true + + var executionCount: UInt = 0 + var hadUnexpectedFailure = false + + let fails = gatherFailingExpectations(silently: true) { + for specClass in specClasses { + for (_, test) in specClass.allTests { + do { + try test(specClass.init())() + } catch { + hadUnexpectedFailure = true + } + executionCount += 1 + } + } + } + + return TestRun(executionCount: executionCount, hasSucceeded: fails.isEmpty && !hadUnexpectedFailure) +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift new file mode 100644 index 0000000..3ef0d6c --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift @@ -0,0 +1,9 @@ +public struct TestRun { + public var executionCount: UInt + public var hasSucceeded: Bool + + public init(executionCount: UInt, hasSucceeded: Bool) { + self.executionCount = executionCount + self.hasSucceeded = hasSucceeded + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..304eb30 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift @@ -0,0 +1,52 @@ +import Foundation +import XCTest + +// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a +// mechanism for us to fail tests in Xcode which haven't been included in the `allTests` +// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note +// that only `static var allTests` needs to be explicitly implemented, as `allTestNames` +// has a default implementation provided by a protocol extension. + +// Implementation note: This is broken down into two separate protocols because we need a +// protocol with no Self references to which we can cast XCTestCase instances in a non-generic context. + +public protocol XCTestCaseProviderStatic { + // This should be explicitly implemented by XCTestCase subclasses + static var allTests: [(String, (Self) -> () throws -> Void)] { get } +} + +public protocol XCTestCaseNameProvider { + // This does not need to be explicitly implemented because of the protocol extension below + var allTestNames: [String] { get } +} + +public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {} + +public extension XCTestCaseProvider where Self: XCTestCaseProviderStatic { + var allTestNames: [String] { + return type(of: self).allTests.map { name, _ in + return name + } + } +} + +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + + extension XCTestCase { + override open func tearDown() { + if let provider = self as? XCTestCaseNameProvider { + provider.assertContainsTest(invocation!.selector.description) + } + + super.tearDown() + } + } + + extension XCTestCaseNameProvider { + fileprivate func assertContainsTest(_ name: String) { + let contains = self.allTestNames.contains(name) + XCTAssert(contains, "Test '\(name)' is missing from the allTests array") + } + } + +#endif diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift new file mode 100644 index 0000000..7e004d1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_BehaviorTests_Behaviors.swift @@ -0,0 +1,20 @@ +import Foundation +import Quick +import Nimble + +class FunctionalTests_BehaviorTests_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> String) { + it("passed the correct parameters via the context") { + let callsite = aContext() + expect(callsite).to(equal("BehaviorSpec")) + } + } +} + +class FunctionalTests_BehaviorTests_Behavior2: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("passes once") { expect(true).to(beTruthy()) } + it("passes twice") { expect(true).to(beTruthy()) } + it("passes three times") { expect(true).to(beTruthy()) } + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift new file mode 100644 index 0000000..e5eed68 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift @@ -0,0 +1,20 @@ +import Foundation +import Quick +import Nimble + +class FunctionalTests_SharedExamplesTests_SharedExamples: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("a group of three shared examples") { + it("passes once") { expect(true).to(beTruthy()) } + it("passes twice") { expect(true).to(beTruthy()) } + it("passes three times") { expect(true).to(beTruthy()) } + } + + sharedExamples("shared examples that take a context") { (sharedExampleContext: @escaping SharedExampleContext) in + it("is passed the correct parameters via the context") { + let callsite = sharedExampleContext()["callsite"] as? String + expect(callsite).to(equal("SharedExamplesSpec")) + } + } + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift new file mode 100644 index 0000000..45f6203 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift @@ -0,0 +1,92 @@ +import XCTest +import Quick +import Nimble + +private enum AfterEachType { + case outerOne + case outerTwo + case outerThree + case innerOne + case innerTwo + case noExamples +} + +private var afterEachOrder = [AfterEachType]() + +class FunctionalTests_AfterEachSpec: QuickSpec { + override func spec() { + describe("afterEach ordering") { + afterEach { afterEachOrder.append(.outerOne) } + afterEach { afterEachOrder.append(.outerTwo) } + afterEach { afterEachOrder.append(.outerThree) } + + it("executes the outer afterEach closures once, but not before this closure [1]") { + // No examples have been run, so no afterEach will have been run either. + // The list should be empty. + expect(afterEachOrder).to(beEmpty()) + } + + it("executes the outer afterEach closures a second time, but not before this closure [2]") { + // The afterEach for the previous example should have been run. + // The list should contain the afterEach for that example, executed from top to bottom. + expect(afterEachOrder).to(equal([.outerOne, .outerTwo, .outerThree])) + } + + context("when there are nested afterEach") { + afterEach { afterEachOrder.append(.innerOne) } + afterEach { afterEachOrder.append(.innerTwo) } + + it("executes the outer and inner afterEach closures, but not before this closure [3]") { + // The afterEach for the previous two examples should have been run. + // The list should contain the afterEach for those example, executed from top to bottom. + expect(afterEachOrder).to(equal([ + .outerOne, .outerTwo, .outerThree, + .outerOne, .outerTwo, .outerThree + ])) + } + } + + context("when there are nested afterEach without examples") { + afterEach { afterEachOrder.append(.noExamples) } + } + } +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + describe("error handling when misusing ordering") { + it("should throw an exception when including afterEach in it block") { + expect { + afterEach { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'afterEach' cannot be used inside 'it', 'afterEach' may only be used inside 'context' or 'describe'. ")) + }) + } + } +#endif + } +} + +final class AfterEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (AfterEachTests) -> () throws -> Void)] { + return [ + ("testAfterEachIsExecutedInTheCorrectOrder", testAfterEachIsExecutedInTheCorrectOrder) + ] + } + + func testAfterEachIsExecutedInTheCorrectOrder() { + afterEachOrder = [] + + qck_runSpec(FunctionalTests_AfterEachSpec.self) + let expectedOrder: [AfterEachType] = [ + // [1] The outer afterEach closures are executed from top to bottom. + .outerOne, .outerTwo, .outerThree, + // [2] The outer afterEach closures are executed from top to bottom. + .outerOne, .outerTwo, .outerThree, + // [3] The inner afterEach closures are executed from top to bottom, + // then the outer afterEach closures are executed from top to bottom. + .innerOne, .innerTwo, .outerOne, .outerTwo, .outerThree + ] + XCTAssertEqual(afterEachOrder, expectedOrder) + + afterEachOrder = [] + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift new file mode 100644 index 0000000..6709051 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift @@ -0,0 +1,75 @@ +import XCTest +import Quick +import Nimble + +private enum BeforeEachType { + case outerOne + case outerTwo + case innerOne + case innerTwo + case innerThree + case noExamples +} + +private var beforeEachOrder = [BeforeEachType]() + +class FunctionalTests_BeforeEachSpec: QuickSpec { + override func spec() { + + describe("beforeEach ordering") { + beforeEach { beforeEachOrder.append(.outerOne) } + beforeEach { beforeEachOrder.append(.outerTwo) } + + it("executes the outer beforeEach closures once [1]") {} + it("executes the outer beforeEach closures a second time [2]") {} + + context("when there are nested beforeEach") { + beforeEach { beforeEachOrder.append(.innerOne) } + beforeEach { beforeEachOrder.append(.innerTwo) } + beforeEach { beforeEachOrder.append(.innerThree) } + + it("executes the outer and inner beforeEach closures [3]") {} + } + + context("when there are nested beforeEach without examples") { + beforeEach { beforeEachOrder.append(.noExamples) } + } + } +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + describe("error handling when misusing ordering") { + it("should throw an exception when including beforeEach in it block") { + expect { + beforeEach { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'beforeEach' cannot be used inside 'it', 'beforeEach' may only be used inside 'context' or 'describe'. ")) + }) + } + } +#endif + } +} + +final class BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeforeEachTests) -> () throws -> Void)] { + return [ + ("testBeforeEachIsExecutedInTheCorrectOrder", testBeforeEachIsExecutedInTheCorrectOrder) + ] + } + + func testBeforeEachIsExecutedInTheCorrectOrder() { + beforeEachOrder = [] + + qck_runSpec(FunctionalTests_BeforeEachSpec.self) + let expectedOrder: [BeforeEachType] = [ + // [1] The outer beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, + // [2] The outer beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, + // [3] The outer beforeEach closures are executed from top to bottom, + // then the inner beforeEach closures are executed from top to bottom. + .outerOne, .outerTwo, .innerOne, .innerTwo, .innerThree + ] + XCTAssertEqual(beforeEachOrder, expectedOrder) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift new file mode 100644 index 0000000..df39126 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift @@ -0,0 +1,39 @@ +import XCTest +import Quick +import Nimble + +var beforeSuiteWasExecuted = false + +class FunctionalTests_BeforeSuite_BeforeSuiteSpec: QuickSpec { + override func spec() { + beforeSuite { + beforeSuiteWasExecuted = true + } + } +} + +class FunctionalTests_BeforeSuite_Spec: QuickSpec { + override func spec() { + it("is executed after beforeSuite") { + expect(beforeSuiteWasExecuted).to(beTruthy()) + } + } +} + +final class BeforeSuiteTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (BeforeSuiteTests) -> () throws -> Void)] { + return [ + ("testBeforeSuiteIsExecutedBeforeAnyExamples", testBeforeSuiteIsExecutedBeforeAnyExamples) + ] + } + + func testBeforeSuiteIsExecutedBeforeAnyExamples() { + // Execute the spec with an assertion before the one with a beforeSuite + let result = qck_runSpecs([ + FunctionalTests_BeforeSuite_Spec.self, + FunctionalTests_BeforeSuite_BeforeSuiteSpec.self + ]) + + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift new file mode 100644 index 0000000..21dadfe --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BehaviorTests.swift @@ -0,0 +1,59 @@ +import Foundation +import Quick +import Nimble +import XCTest + +class FunctionalTests_BehaviorTests_Spec: QuickSpec { + override func spec() { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior2.self) { () -> Void in } + } +} + +class FunctionalTests_BehaviorTests_ContextSpec: QuickSpec { + override func spec() { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior.self) { + "BehaviorSpec" + } + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class FunctionalTests_BehaviorTests_ErrorSpec: QuickSpec { + override func spec() { + describe("error handling when misusing ordering") { + it("should throw an exception when including itBehavesLike in it block") { + expect { + itBehavesLike(FunctionalTests_BehaviorTests_Behavior2.self) { () } + } + .to(raiseException {(exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'itBehavesLike' cannot be used inside 'it', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif + +final class BehaviorTests: XCTestCase, XCTestCaseProvider { + + static var allTests: [(String, (BehaviorTests) -> () throws -> Void)] { + return [ + ("testBehaviorPassContextToExamples", + testBehaviorPassContextToExamples), + ("testBehaviorExecutesThreeExamples", + testBehaviorExecutesThreeExamples) + ] + } + + func testBehaviorExecutesThreeExamples() { + let result = qck_runSpec(FunctionalTests_BehaviorTests_Spec.self) + XCTAssert(result!.hasSucceeded) + XCTAssertEqual(result!.executionCount, 3) + } + + func testBehaviorPassContextToExamples() { + let result = qck_runSpec(FunctionalTests_BehaviorTests_ContextSpec.self) + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift new file mode 100644 index 0000000..4f99689 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift @@ -0,0 +1,30 @@ +#if !SWIFT_PACKAGE + +import XCTest +@testable import Quick +import Nimble + +class BundleModuleNameSpecs: QuickSpec { + override func spec() { + describe("Bundle module name") { + it("should repalce invalid characters with underscores") { + let bundle = Bundle.currentTestBundle + let moduleName = bundle?.moduleName + expect(moduleName?.contains("Quick_")).to(beTrue()) + } + + it("should be the correct module name to be able to retreive classes") { + guard let bundle = Bundle.currentTestBundle else { + XCTFail("test bundle not found") + return + } + + let moduleName = bundle.moduleName + let className: AnyClass? = NSClassFromString("\(moduleName).BundleModuleNameSpecs") + expect(className).to(be(BundleModuleNameSpecs.self)) + } + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift new file mode 100644 index 0000000..c3f6717 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift @@ -0,0 +1,11 @@ +import Quick + +public var FunctionalTests_Configuration_AfterEachWasExecuted = false + +class FunctionalTests_Configuration_AfterEach: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.afterEach { + FunctionalTests_Configuration_AfterEachWasExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift new file mode 100644 index 0000000..d7c2105 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift @@ -0,0 +1,31 @@ +import XCTest +import Quick +import Nimble + +class Configuration_AfterEachSpec: QuickSpec { + override func spec() { + beforeEach { + FunctionalTests_Configuration_AfterEachWasExecuted = false + } + it("is executed before the configuration afterEach") { + expect(FunctionalTests_Configuration_AfterEachWasExecuted).to(beFalsy()) + } + } +} + +final class Configuration_AfterEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (Configuration_AfterEachTests) -> () throws -> Void)] { + return [ + ("testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted", testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted) + ] + } + + func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { + FunctionalTests_Configuration_AfterEachWasExecuted = false + + qck_runSpec(Configuration_BeforeEachSpec.self) + XCTAssert(FunctionalTests_Configuration_AfterEachWasExecuted) + + FunctionalTests_Configuration_AfterEachWasExecuted = false + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift new file mode 100644 index 0000000..228ab98 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift @@ -0,0 +1,11 @@ +import Quick + +public var FunctionalTests_Configuration_BeforeEachWasExecuted = false + +class FunctionalTests_Configuration_BeforeEach: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + configuration.beforeEach { + FunctionalTests_Configuration_BeforeEachWasExecuted = true + } + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift new file mode 100644 index 0000000..ddf1509 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift @@ -0,0 +1,28 @@ +import XCTest +import Quick +import Nimble + +class Configuration_BeforeEachSpec: QuickSpec { + override func spec() { + it("is executed after the configuration beforeEach") { + expect(FunctionalTests_Configuration_BeforeEachWasExecuted).to(beTruthy()) + } + } +} + +final class Configuration_BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (Configuration_BeforeEachTests) -> () throws -> Void)] { + return [ + ("testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted", testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted) + ] + } + + func testExampleIsRunAfterTheConfigurationBeforeEachIsExecuted() { + FunctionalTests_Configuration_BeforeEachWasExecuted = false + + qck_runSpec(Configuration_BeforeEachSpec.self) + XCTAssert(FunctionalTests_Configuration_BeforeEachWasExecuted) + + FunctionalTests_Configuration_BeforeEachWasExecuted = false + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift new file mode 100644 index 0000000..ab619be --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift @@ -0,0 +1,20 @@ +import XCTest +import Quick +import Nimble + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class QuickContextTests: QuickSpec { + override func spec() { + describe("Context") { + it("should throw an exception if used in an it block") { + expect { + context("A nested context that should throw") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'context' cannot be used inside 'it', 'context' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift new file mode 100644 index 0000000..5fc3d7b --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift @@ -0,0 +1,19 @@ +import Quick +import Nimble + +// This is a functional test ensuring that no crash occurs when a spec class +// references another spec class during its spec setup. + +class FunctionalTests_CrossReferencingSpecA: QuickSpec { + override func spec() { + _ = FunctionalTests_CrossReferencingSpecB() + it("does not crash") {} + } +} + +class FunctionalTests_CrossReferencingSpecB: QuickSpec { + override func spec() { + _ = FunctionalTests_CrossReferencingSpecA() + it("does not crash") {} + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift new file mode 100644 index 0000000..05b37f7 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CurrentSpecTests.swift @@ -0,0 +1,25 @@ +import Quick +import Nimble + +#if !SWIFT_PACKAGE + +class CurrentSpecTests: QuickSpec { + override func spec() { + it("returns the currently executing spec") { + expect(QuickSpec.current?.name).to(match("currently_executing_spec")) + } + + let currentSpecDuringSpecSetup = QuickSpec.current + it("returns nil when no spec is executing") { + expect(currentSpecDuringSpecSetup).to(beNil()) + } + + it("supports XCTest expectations") { + let expectation = QuickSpec.current.expectation(description: "great expectation") + DispatchQueue.main.async(execute: expectation.fulfill) + QuickSpec.current.waitForExpectations(timeout: 1) + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift new file mode 100644 index 0000000..6c4ac07 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift @@ -0,0 +1,34 @@ +import XCTest +import Nimble +import Quick + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + +final class DescribeTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (DescribeTests) -> () throws -> Void)] { + return [ + ("testDescribeThrowsIfUsedOutsideOfQuickSpec", testDescribeThrowsIfUsedOutsideOfQuickSpec) + ] + } + + func testDescribeThrowsIfUsedOutsideOfQuickSpec() { + expect { describe("this should throw an exception", {}) }.to(raiseException()) + } +} + +class QuickDescribeTests: QuickSpec { + override func spec() { + describe("Describe") { + it("should throw an exception if used in an it block") { + expect { + describe("A nested describe that should throw") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'describe' cannot be used inside 'it', 'describe' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} + +#endif diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift new file mode 100644 index 0000000..106cf30 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift @@ -0,0 +1,127 @@ +import XCTest +@testable import Quick +import Nimble + +class FunctionalTests_ItSpec: QuickSpec { + override func spec() { + var exampleMetadata: ExampleMetadata? + beforeEach { metadata in exampleMetadata = metadata } + + it("") { + expect(exampleMetadata!.example.name).to(equal("")) + } + + it("has a description with セレクター名に使えない文字が入っている 👊💥") { + let name = "has a description with セレクター名に使えない文字が入っている 👊💥" + expect(exampleMetadata!.example.name).to(equal(name)) + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + + describe("when an example has a unique name") { + it("has a unique name") {} + + it("doesn't add multiple selectors for it") { + let allSelectors = [String]( + FunctionalTests_ItSpec.allSelectors() + .filter { $0.hasPrefix("when_an_example_has_a_unique_name__") }) + .sorted(by: <) + + expect(allSelectors) == [ + "when_an_example_has_a_unique_name__doesn_t_add_multiple_selectors_for_it", + "when_an_example_has_a_unique_name__has_a_unique_name" + ] + } + } + + describe("when two examples have the exact name") { + it("has exactly the same name") {} + it("has exactly the same name") {} + + it("makes a unique name for each of the above") { + let allSelectors = [String]( + FunctionalTests_ItSpec.allSelectors() + .filter { $0.hasPrefix("when_two_examples_have_the_exact_name__") }) + .sorted(by: <) + + expect(allSelectors) == [ + "when_two_examples_have_the_exact_name__has_exactly_the_same_name", + "when_two_examples_have_the_exact_name__has_exactly_the_same_name_2", + "when_two_examples_have_the_exact_name__makes_a_unique_name_for_each_of_the_above" + ] + } + + } + + describe("error handling when misusing ordering") { + it("an it") { + expect { + it("will throw an error when it is nested in another it") { } + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ")) + }) + } + + describe("behavior with an 'it' inside a 'beforeEach'") { + var exception: NSException? + + beforeEach { + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + it("a rogue 'it' inside a 'beforeEach'") { } + return + } + } + + it("should have thrown an exception with the correct error message") { + expect(exception).toNot(beNil()) + expect(exception!.reason).to(equal("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ")) + } + } + + describe("behavior with an 'it' inside an 'afterEach'") { + var exception: NSException? + + afterEach { + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + expect(exception).toNot(beNil()) + expect(exception!.reason).to(equal("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ")) + }), finally: nil) + + capture.tryBlock { + it("a rogue 'it' inside an 'afterEach'") { } + return + } + } + + it("should throw an exception with the correct message after this 'it' block executes") { } + } + } +#endif + } +} + +final class ItTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (ItTests) -> () throws -> Void)] { + return [ + ("testAllExamplesAreExecuted", testAllExamplesAreExecuted) + ] + } + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 10) + } +#else + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 2) + } +#endif +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m new file mode 100644 index 0000000..4216a86 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m @@ -0,0 +1,81 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +typedef NS_ENUM(NSUInteger, AfterEachType) { + OuterOne, + OuterTwo, + OuterThree, + InnerOne, + InnerTwo, + NoExamples, +}; + +static NSMutableArray *afterEachOrder; + +QuickSpecBegin(FunctionalTests_AfterEachSpec_ObjC) + +afterEach(^{ [afterEachOrder addObject:@(OuterOne)]; }); +afterEach(^{ [afterEachOrder addObject:@(OuterTwo)]; }); +afterEach(^{ [afterEachOrder addObject:@(OuterThree)]; }); + +it(@"executes the outer afterEach closures once, but not before this closure [1]", ^{ + expect(afterEachOrder).to(equal(@[])); +}); + +it(@"executes the outer afterEach closures a second time, but not before this closure [2]", ^{ + expect(afterEachOrder).to(equal(@[@(OuterOne), @(OuterTwo), @(OuterThree)])); +}); + +context(@"when there are nested afterEach", ^{ + afterEach(^{ [afterEachOrder addObject:@(InnerOne)]; }); + afterEach(^{ [afterEachOrder addObject:@(InnerTwo)]; }); + + it(@"executes the outer and inner afterEach closures, but not before this closure [3]", ^{ + // The afterEach for the previous two examples should have been run. + // The list should contain the afterEach for those example, executed from top to bottom. + expect(afterEachOrder).to(equal(@[ + @(OuterOne), @(OuterTwo), @(OuterThree), + @(OuterOne), @(OuterTwo), @(OuterThree), + ])); + }); +}); + +context(@"when there are nested afterEach without examples", ^{ + afterEach(^{ [afterEachOrder addObject:@(NoExamples)]; }); +}); + +QuickSpecEnd + +@interface AfterEachTests_ObjC : XCTestCase; @end + +@implementation AfterEachTests_ObjC + +- (void)setUp { + [super setUp]; + afterEachOrder = [NSMutableArray array]; +} + +- (void)tearDown { + afterEachOrder = [NSMutableArray array]; + [super tearDown]; +} + +- (void)testAfterEachIsExecutedInTheCorrectOrder { + qck_runSpec([FunctionalTests_AfterEachSpec_ObjC class]); + NSArray *expectedOrder = @[ + // [1] The outer afterEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(OuterThree), + // [2] The outer afterEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(OuterThree), + // [3] The outer afterEach closures are executed from top to bottom, + // then the outer afterEach closures are executed from top to bottom. + @(InnerOne), @(InnerTwo), @(OuterOne), @(OuterTwo), @(OuterThree), + ]; + + XCTAssertEqualObjects(afterEachOrder, expectedOrder); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m new file mode 100644 index 0000000..c7a5897 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m @@ -0,0 +1,68 @@ +@import XCTest; +@import Quick; + +#import "QCKSpecRunner.h" + +typedef NS_ENUM(NSUInteger, BeforeEachType) { + OuterOne, + OuterTwo, + InnerOne, + InnerTwo, + InnerThree, + NoExamples, +}; + +static NSMutableArray *beforeEachOrder; + +QuickSpecBegin(FunctionalTests_BeforeEachSpec_ObjC) + +beforeEach(^{ [beforeEachOrder addObject:@(OuterOne)]; }); +beforeEach(^{ [beforeEachOrder addObject:@(OuterTwo)]; }); + +it(@"executes the outer beforeEach closures once [1]", ^{}); +it(@"executes the outer beforeEach closures a second time [2]", ^{}); + +context(@"when there are nested beforeEach", ^{ + beforeEach(^{ [beforeEachOrder addObject:@(InnerOne)]; }); + beforeEach(^{ [beforeEachOrder addObject:@(InnerTwo)]; }); + beforeEach(^{ [beforeEachOrder addObject:@(InnerThree)]; }); + + it(@"executes the outer and inner beforeEach closures [3]", ^{}); +}); + +context(@"when there are nested beforeEach without examples", ^{ + beforeEach(^{ [beforeEachOrder addObject:@(NoExamples)]; }); +}); + +QuickSpecEnd + +@interface BeforeEachTests_ObjC : XCTestCase; @end + +@implementation BeforeEachTests_ObjC + +- (void)setUp { + beforeEachOrder = [NSMutableArray array]; + [super setUp]; +} + +- (void)tearDown { + beforeEachOrder = [NSMutableArray array]; + [super tearDown]; +} + +- (void)testBeforeEachIsExecutedInTheCorrectOrder { + qck_runSpec([FunctionalTests_BeforeEachSpec_ObjC class]); + NSArray *expectedOrder = @[ + // [1] The outer beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), + // [2] The outer beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), + // [3] The outer beforeEach closures are executed from top to bottom, + // then the inner beforeEach closures are executed from top to bottom. + @(OuterOne), @(OuterTwo), @(InnerOne), @(InnerTwo), @(InnerThree), + ]; + + XCTAssertEqualObjects(beforeEachOrder, expectedOrder); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m new file mode 100644 index 0000000..ce7efc9 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m @@ -0,0 +1,39 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static BOOL beforeSuiteWasExecuted = NO; + +QuickSpecBegin(FunctionalTests_BeforeSuite_BeforeSuiteSpec_ObjC) + +beforeSuite(^{ + beforeSuiteWasExecuted = YES; +}); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_BeforeSuite_Spec_ObjC) + +it(@"is executed after beforeSuite", ^{ + expect(@(beforeSuiteWasExecuted)).to(beTruthy()); +}); + +QuickSpecEnd + +@interface BeforeSuiteTests_ObjC : XCTestCase; @end + +@implementation BeforeSuiteTests_ObjC + +- (void)testBeforeSuiteIsExecutedBeforeAnyExamples { + // Execute the spec with an assertion before the one with a beforeSuite + NSArray *specs = @[ + [FunctionalTests_BeforeSuite_Spec_ObjC class], + [FunctionalTests_BeforeSuite_BeforeSuiteSpec_ObjC class] + ]; + XCTestRun *result = qck_runSpecs(specs); + XCTAssert(result.hasSucceeded); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m new file mode 100644 index 0000000..dc786e8 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m @@ -0,0 +1,61 @@ +@import XCTest; + +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static BOOL isRunningFunctionalTests = NO; + +#pragma mark - Spec + +QuickSpecBegin(FunctionalTests_FailureSpec_ObjC) + +describe(@"a group of failing examples", ^{ + it(@"passes", ^{ + expect(@YES).to(beTruthy()); + }); + + it(@"fails (but only when running the functional tests)", ^{ + expect(@(isRunningFunctionalTests)).to(beFalsy()); + }); + + it(@"fails again (but only when running the functional tests)", ^{ + expect(@(isRunningFunctionalTests)).to(beFalsy()); + }); +}); + +QuickSpecEnd + +#pragma mark - Tests + +@interface FailureTests_ObjC : XCTestCase; @end + +@implementation FailureTests_ObjC + +- (void)setUp { + [super setUp]; + isRunningFunctionalTests = YES; +} + +- (void)tearDown { + isRunningFunctionalTests = NO; + [super tearDown]; +} + +- (void)testFailureSpecHasSucceededIsFalse { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertFalse(result.hasSucceeded); +} + +- (void)testFailureSpecExecutedAllExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testFailureSpecFailureCountIsEqualToTheNumberOfFailingExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureSpec_ObjC class]); + XCTAssertEqual(result.failureCount, 2); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m new file mode 100644 index 0000000..70fb245 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m @@ -0,0 +1,55 @@ +@import XCTest; +@import Quick; + +#import "QCKSpecRunner.h" + +static BOOL isRunningFunctionalTests = NO; + +QuickSpecBegin(FunctionalTests_FailureUsingXCTAssertSpec_ObjC) + +it(@"fails using an XCTAssert (but only when running the functional tests)", ^{ + XCTAssertFalse(isRunningFunctionalTests); +}); + +it(@"fails again using an XCTAssert (but only when running the functional tests)", ^{ + XCTAssertFalse(isRunningFunctionalTests); +}); + +it(@"succeeds using an XCTAssert", ^{ + XCTAssertTrue(YES); +}); + +QuickSpecEnd + +#pragma mark - Tests + +@interface FailureUsingXCTAssertTests_ObjC : XCTestCase; @end + +@implementation FailureUsingXCTAssertTests_ObjC + +- (void)setUp { + [super setUp]; + isRunningFunctionalTests = YES; +} + +- (void)tearDown { + isRunningFunctionalTests = NO; + [super tearDown]; +} + +- (void)testFailureUsingXCTAssertSpecHasSucceededIsFalse { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertFalse(result.hasSucceeded); +} + +- (void)testFailureUsingXCTAssertSpecExecutedAllExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testFailureUsingXCTAssertSpecFailureCountIsEqualToTheNumberOfFailingExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_FailureUsingXCTAssertSpec_ObjC class]); + XCTAssertEqual(result.totalFailureCount, 2); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m new file mode 100644 index 0000000..39e0b7d --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m @@ -0,0 +1,42 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" +#import "QuickSpec+QuickSpec_MethodList.h" + +QuickSpecBegin(FunctionalTests_ItSpec_ObjC) + +__block ExampleMetadata *exampleMetadata = nil; +beforeEachWithMetadata(^(ExampleMetadata *metadata) { + exampleMetadata = metadata; +}); + +it(@" ", ^{ + expect(exampleMetadata.example.name).to(equal(@" ")); +}); + +it(@"has a description with セレクター名に使えない文字が入っている 👊💥", ^{ + NSString *name = @"has a description with セレクター名に使えない文字が入っている 👊💥"; + expect(exampleMetadata.example.name).to(equal(name)); +}); + +it(@"is a test with a unique name", ^{ + NSSet *allSelectors = [FunctionalTests_ItSpec_ObjC allSelectors]; + + expect(allSelectors).to(contain(@"is_a_test_with_a_unique_name")); + expect(allSelectors).toNot(contain(@"is_a_test_with_a_unique_name_2")); +}); + +QuickSpecEnd + +@interface ItTests_ObjC : XCTestCase; @end + +@implementation ItTests_ObjC + +- (void)testAllExamplesAreExecuted { + XCTestRun *result = qck_runSpec([FunctionalTests_ItSpec_ObjC class]); + XCTAssertEqual(result.executionCount, 3); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m new file mode 100644 index 0000000..970175f --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m @@ -0,0 +1,60 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static NSUInteger oneExampleBeforeEachExecutedCount = 0; +static NSUInteger onlyPendingExamplesBeforeEachExecutedCount = 0; + +QuickSpecBegin(FunctionalTests_PendingSpec_ObjC) + +pending(@"an example that will not run", ^{ + expect(@YES).to(beFalsy()); +}); + +describe(@"a describe block containing only one enabled example", ^{ + beforeEach(^{ oneExampleBeforeEachExecutedCount += 1; }); + it(@"an example that will run", ^{}); + pending(@"an example that will not run", ^{}); +}); + +describe(@"a describe block containing only pending examples", ^{ + beforeEach(^{ onlyPendingExamplesBeforeEachExecutedCount += 1; }); + pending(@"an example that will not run", ^{}); +}); + +QuickSpecEnd + +@interface PendingTests_ObjC : XCTestCase; @end + +@implementation PendingTests_ObjC + +- (void)setUp { + [super setUp]; + oneExampleBeforeEachExecutedCount = 0; + onlyPendingExamplesBeforeEachExecutedCount = 0; +} + +- (void)tearDown { + oneExampleBeforeEachExecutedCount = 0; + onlyPendingExamplesBeforeEachExecutedCount = 0; + [super tearDown]; +} + +- (void)testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail { + XCTestRun *result = qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssert(result.hasSucceeded); +} + +- (void)testBeforeEachOnlyRunForEnabledExamples { + qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssertEqual(oneExampleBeforeEachExecutedCount, 1); +} + +- (void)testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples { + qck_runSpec([FunctionalTests_PendingSpec_ObjC class]); + XCTAssertEqual(onlyPendingExamplesBeforeEachExecutedCount, 0); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m new file mode 100644 index 0000000..cdbf259 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m @@ -0,0 +1,59 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +static NSUInteger specBeforeEachExecutedCount = 0; +static NSUInteger sharedExamplesBeforeEachExecutedCount = 0; + +QuickConfigurationBegin(FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples_ObjC) + ++ (void)configure:(Configuration *)configuration { + sharedExamples(@"a group of three shared examples with a beforeEach in Obj-C", + ^(QCKDSLSharedExampleContext context) { + beforeEach(^{ sharedExamplesBeforeEachExecutedCount += 1; }); + it(@"passes once", ^{}); + it(@"passes twice", ^{}); + it(@"passes three times", ^{}); + }); +} + +QuickConfigurationEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_BeforeEachSpec_ObjC) + +beforeEach(^{ specBeforeEachExecutedCount += 1; }); +it(@"executes the spec beforeEach once", ^{}); +itBehavesLike(@"a group of three shared examples with a beforeEach in Obj-C", + ^NSDictionary*{ return @{}; }); + +QuickSpecEnd + +@interface SharedExamples_BeforeEachTests_ObjC : XCTestCase; @end + +@implementation SharedExamples_BeforeEachTests_ObjC + +- (void)setUp { + [super setUp]; + specBeforeEachExecutedCount = 0; + sharedExamplesBeforeEachExecutedCount = 0; +} + +- (void)tearDown { + specBeforeEachExecutedCount = 0; + sharedExamplesBeforeEachExecutedCount = 0; + [super tearDown]; +} + +- (void)testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample { + qck_runSpec([FunctionalTests_SharedExamples_BeforeEachSpec_ObjC class]); + XCTAssertEqual(specBeforeEachExecutedCount, 4); +} + +- (void)testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample { + qck_runSpec([FunctionalTests_SharedExamples_BeforeEachSpec_ObjC class]); + XCTAssertEqual(sharedExamplesBeforeEachExecutedCount, 3); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m new file mode 100644 index 0000000..7fcb8b1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m @@ -0,0 +1,65 @@ +@import XCTest; +@import Quick; +@import Nimble; + +#import "QCKSpecRunner.h" + +QuickSpecBegin(FunctionalTests_SharedExamples_Spec_ObjC) + +itBehavesLike(@"a group of three shared examples", ^NSDictionary*{ return @{}; }); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_ContextSpec_ObjC) + +itBehavesLike(@"shared examples that take a context", ^NSDictionary *{ + return @{ @"callsite": @"SharedExamplesSpec" }; +}); + +QuickSpecEnd + +QuickSpecBegin(FunctionalTests_SharedExamples_SameContextSpec_ObjC) + +__block NSInteger counter = 0; + +afterEach(^{ + counter++; +}); + +sharedExamples(@"gets called with a different context from within the same spec file", ^(QCKDSLSharedExampleContext exampleContext) { + + it(@"tracks correctly", ^{ + NSString *payload = exampleContext()[@"payload"]; + BOOL expected = [payload isEqualToString:[NSString stringWithFormat:@"%ld", (long)counter]]; + expect(@(expected)).to(beTrue()); + }); + +}); + +itBehavesLike(@"gets called with a different context from within the same spec file", ^{ + return @{ @"payload" : @"0" }; +}); + +itBehavesLike(@"gets called with a different context from within the same spec file", ^{ + return @{ @"payload" : @"1" }; +}); + +QuickSpecEnd + + +@interface SharedExamplesTests_ObjC : XCTestCase; @end + +@implementation SharedExamplesTests_ObjC + +- (void)testAGroupOfThreeSharedExamplesExecutesThreeExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_SharedExamples_Spec_ObjC class]); + XCTAssert(result.hasSucceeded); + XCTAssertEqual(result.executionCount, 3); +} + +- (void)testSharedExamplesWithContextPassContextToExamples { + XCTestRun *result = qck_runSpec([FunctionalTests_SharedExamples_ContextSpec_ObjC class]); + XCTAssert(result.hasSucceeded); +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift new file mode 100644 index 0000000..5334200 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift @@ -0,0 +1,61 @@ +import XCTest +import Quick +import Nimble + +var oneExampleBeforeEachExecutedCount = 0 +var onlyPendingExamplesBeforeEachExecutedCount = 0 + +class FunctionalTests_PendingSpec_Behavior: Behavior { + override static func spec(_ aContext: @escaping () -> Void) { + it("an example that will not run") { + expect(true).to(beFalsy()) + } + } +} +class FunctionalTests_PendingSpec: QuickSpec { + override func spec() { + xit("an example that will not run") { + expect(true).to(beFalsy()) + } + xitBehavesLike(FunctionalTests_PendingSpec_Behavior.self) { () -> Void in } + describe("a describe block containing only one enabled example") { + beforeEach { oneExampleBeforeEachExecutedCount += 1 } + it("an example that will run") {} + pending("an example that will not run") {} + } + + describe("a describe block containing only pending examples") { + beforeEach { onlyPendingExamplesBeforeEachExecutedCount += 1 } + pending("an example that will not run") {} + } + } +} + +final class PendingTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (PendingTests) -> () throws -> Void)] { + return [ + ("testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail", testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail), + ("testBeforeEachOnlyRunForEnabledExamples", testBeforeEachOnlyRunForEnabledExamples), + ("testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples", testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples) + ] + } + + func testAnOtherwiseFailingExampleWhenMarkedPendingDoesNotCauseTheSuiteToFail() { + let result = qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertTrue(result!.hasSucceeded) + } + + func testBeforeEachOnlyRunForEnabledExamples() { + oneExampleBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertEqual(oneExampleBeforeEachExecutedCount, 1) + } + + func testBeforeEachDoesNotRunForContextsWithOnlyPendingExamples() { + onlyPendingExamplesBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_PendingSpec.self) + XCTAssertEqual(onlyPendingExamplesBeforeEachExecutedCount, 0) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift new file mode 100644 index 0000000..2b0fd77 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift @@ -0,0 +1,48 @@ +import XCTest +import Quick +import Nimble + +var specBeforeEachExecutedCount = 0 +var sharedExamplesBeforeEachExecutedCount = 0 + +class FunctionalTests_SharedExamples_BeforeEachTests_SharedExamples: QuickConfiguration { + override class func configure(_ configuration: Configuration) { + sharedExamples("a group of three shared examples with a beforeEach") { + beforeEach { sharedExamplesBeforeEachExecutedCount += 1 } + it("passes once") {} + it("passes twice") {} + it("passes three times") {} + } + } +} + +class FunctionalTests_SharedExamples_BeforeEachSpec: QuickSpec { + override func spec() { + beforeEach { specBeforeEachExecutedCount += 1 } + it("executes the spec beforeEach once") {} + itBehavesLike("a group of three shared examples with a beforeEach") + } +} + +final class SharedExamples_BeforeEachTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SharedExamples_BeforeEachTests) -> () throws -> Void)] { + return [ + ("testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample", testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample), + ("testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample", testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample) + ] + } + + func testBeforeEachOutsideOfSharedExamplesExecutedOnceBeforeEachExample() { + specBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.self) + XCTAssertEqual(specBeforeEachExecutedCount, 4) + } + + func testBeforeEachInSharedExamplesExecutedOnceBeforeEachSharedExample() { + sharedExamplesBeforeEachExecutedCount = 0 + + qck_runSpec(FunctionalTests_SharedExamples_BeforeEachSpec.self) + XCTAssertEqual(sharedExamplesBeforeEachExecutedCount, 3) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift new file mode 100644 index 0000000..8a50cc1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift @@ -0,0 +1,54 @@ +import Foundation +import XCTest +import Quick +import Nimble + +class FunctionalTests_SharedExamples_Spec: QuickSpec { + override func spec() { + itBehavesLike("a group of three shared examples") + } +} + +class FunctionalTests_SharedExamples_ContextSpec: QuickSpec { + override func spec() { + itBehavesLike("shared examples that take a context") { ["callsite": "SharedExamplesSpec"] } + } +} + +#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE +class FunctionalTests_SharedExamples_ErrorSpec: QuickSpec { + override func spec() { + describe("error handling when misusing ordering") { + it("should throw an exception when including itBehavesLike in it block") { + expect { + itBehavesLike("a group of three shared examples") + }.to(raiseException { (exception: NSException) in + expect(exception.name).to(equal(NSExceptionName.internalInconsistencyException)) + expect(exception.reason).to(equal("'itBehavesLike' cannot be used inside 'it', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")) + }) + } + } + } +} +#endif + +// Shared examples are defined in QuickTests/Fixtures +final class SharedExamplesTests: XCTestCase, XCTestCaseProvider { + static var allTests: [(String, (SharedExamplesTests) -> () throws -> Void)] { + return [ + ("testAGroupOfThreeSharedExamplesExecutesThreeExamples", testAGroupOfThreeSharedExamplesExecutesThreeExamples), + ("testSharedExamplesWithContextPassContextToExamples", testSharedExamplesWithContextPassContextToExamples) + ] + } + + func testAGroupOfThreeSharedExamplesExecutesThreeExamples() { + let result = qck_runSpec(FunctionalTests_SharedExamples_Spec.self) + XCTAssert(result!.hasSucceeded) + XCTAssertEqual(result!.executionCount, 3) + } + + func testSharedExamplesWithContextPassContextToExamples() { + let result = qck_runSpec(FunctionalTests_SharedExamples_ContextSpec.self) + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h new file mode 100644 index 0000000..183118e --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h @@ -0,0 +1,22 @@ +@import XCTest; + +/** + Runs an XCTestSuite instance containing only the given XCTestCase subclass. + Use this to run QuickSpec subclasses from within a set of unit tests. + + Due to implicit dependencies in _XCTFailureHandler, this function raises an + exception when used in Swift to run a failing test case. + + @param specClass The class of the spec to be run. + @return An XCTestRun instance that contains information such as the number of failures, etc. + */ +extern XCTestRun * _Nullable qck_runSpec(Class _Nonnull specClass); + +/** + Runs an XCTestSuite instance containing the given XCTestCase subclasses, in the order provided. + See the documentation for `qck_runSpec` for more details. + + @param specClasses An array of QuickSpec classes, in the order they should be run. + @return An XCTestRun instance that contains information such as the number of failures, etc. + */ +extern XCTestRun * _Nullable qck_runSpecs(NSArray * _Nonnull specClasses); diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m new file mode 100644 index 0000000..a3437a1 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m @@ -0,0 +1,32 @@ +@import Quick; + +#import "QCKSpecRunner.h" +#import "XCTestObservationCenter+QCKSuspendObservation.h" + +@interface XCTest (Redeclaration) +- (XCTestRun *)run; +@end + +XCTestRun * _Nullable qck_runSuite(XCTestSuite * _Nonnull suite) { + [World sharedWorld].isRunningAdditionalSuites = YES; + + __block XCTestRun *result = nil; + [[XCTestObservationCenter sharedTestObservationCenter] qck_suspendObservationForBlock:^{ + [suite runTest]; + result = suite.testRun; + }]; + return result; +} + +XCTestRun *qck_runSpec(Class specClass) { + return qck_runSuite([XCTestSuite testSuiteForTestCaseClass:specClass]); +} + +XCTestRun * _Nullable qck_runSpecs(NSArray * _Nonnull specClasses) { + XCTestSuite *suite = [XCTestSuite testSuiteWithName:@"MySpecs"]; + for (Class specClass in specClasses) { + [suite addTest:[XCTestSuite testSuiteForTestCaseClass:specClass]]; + } + + return qck_runSuite(suite); +} diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h new file mode 100644 index 0000000..5e5c447 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h @@ -0,0 +1,17 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QuickSpec (QuickSpec_MethodList) + +/** + * This method will instantiate an instance of the class on which it is called, + * returning a list of selector names for it. + * + * @return a set of NSStrings representing the list of selectors it contains + */ ++ (NSSet *)allSelectors; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m new file mode 100644 index 0000000..5a403f2 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m @@ -0,0 +1,23 @@ +#import "QuickSpec+QuickSpec_MethodList.h" +#import + + +@implementation QuickSpec (QuickSpec_MethodList) + ++ (NSSet *)allSelectors { + QuickSpec *specInstance = [[[self class] alloc] init]; + NSMutableSet *allSelectors = [NSMutableSet set]; + + unsigned int methodCount = 0; + Method *methodList = class_copyMethodList(object_getClass(specInstance), &methodCount); + + for (unsigned int i = 0; i < methodCount; i++) { + SEL selector = method_getName(methodList[i]); + [allSelectors addObject:NSStringFromSelector(selector)]; + } + + free(methodList); + return [allSelectors copy]; +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h new file mode 100644 index 0000000..301c5d5 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h @@ -0,0 +1,2 @@ +#import "QCKSpecRunner.h" +#import "QuickSpec+QuickSpec_MethodList.h" diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h new file mode 100644 index 0000000..d69f808 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h @@ -0,0 +1,20 @@ +#import + +/** + Add the ability to temporarily disable internal XCTest execution observation in + order to run isolated XCTestSuite instances while the QuickTests test suite is running. + */ +@interface XCTestObservationCenter (QCKSuspendObservation) + +/** + Suspends test suite observation for XCTest-provided observers for the duration that + the block is executing. Any test suites that are executed within the block do not + generate any log output. Failures are still reported. + + Use this method to run XCTestSuite objects while another XCTestSuite is running. + Without this method, tests fail with the message: "Timed out waiting for IDE + barrier message to complete" or "Unexpected TestSuiteDidStart". + */ +- (void)qck_suspendObservationForBlock:(void (^)(void))block; + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m new file mode 100644 index 0000000..1a32e10 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m @@ -0,0 +1,54 @@ +@import XCTest; +#import + +@interface XCTestObservationCenter (Redeclaration) +- (id)observers; +- (void)removeTestObserver:(id)testObserver; +@end + +@implementation XCTestObservationCenter (QCKSuspendObservation) + +/// This allows us to only suspend observation for observers by provided by Apple +/// as a part of the XCTest framework. In particular it is important that we not +/// suspend the observer added by Nimble, otherwise it is unable to properly +/// report assertion failures. +static BOOL (^isFromApple)(id) = ^BOOL(id observer){ + return [[NSBundle bundleForClass:[observer class]].bundleIdentifier containsString:@"com.apple.dt.XCTest"]; +}; + +- (void)qck_suspendObservationForBlock:(void (^)(void))block { + id originalObservers = [[self observers] copy]; + NSMutableArray *suspendedObservers = [NSMutableArray new]; + + for (id observer in originalObservers) { + if (isFromApple(observer)) { + [suspendedObservers addObject:observer]; + + if ([self respondsToSelector:@selector(removeTestObserver:)]) { + [self removeTestObserver:observer]; + } + else if ([[self observers] respondsToSelector:@selector(removeObject:)]) { + [[self observers] removeObject:observer]; + } + else { + NSAssert(NO, @"unexpected type: unable to remove observers: %@", originalObservers); + } + } + } + + @try { + block(); + } + @finally { + for (id observer in suspendedObservers) { + if ([[self observers] respondsToSelector:@selector(addObject:)]) { + [[self observers] addObject:observer]; + } + else if ([self respondsToSelector:@selector(addTestObserver:)]) { + [self addTestObserver:observer]; + } + } + } +} + +@end diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m new file mode 100644 index 0000000..ace4577 --- /dev/null +++ b/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m @@ -0,0 +1,12 @@ +#import +#import + +@interface QuickConfigurationTests : XCTestCase; @end + +@implementation QuickConfigurationTests + +- (void)testInitThrows { + XCTAssertThrowsSpecificNamed([QuickConfiguration new], NSException, NSInternalInconsistencyException); +} + +@end diff --git a/Carthage/Checkouts/Quick/script/release b/Carthage/Checkouts/Quick/script/release new file mode 100755 index 0000000..26409c4 --- /dev/null +++ b/Carthage/Checkouts/Quick/script/release @@ -0,0 +1,182 @@ +#!/usr/bin/env sh +REMOTE_BRANCH=master +POD_NAME=Quick +PODSPEC=Quick.podspec + +POD=${COCOAPODS:-pod} + +function help { + echo "Usage: release VERSION RELEASE_NOTES [-f]" + echo + echo "VERSION should be the version to release, should not include the 'v' prefix" + echo "RELEASE_NOTES should be a file that lists all the release notes for this version" + echo " if file does not exist, creates a git-style commit with a diff as a comment" + echo + echo "FLAGS" + echo " -f Forces override of tag" + echo + echo " Example: ./release 1.0.0-rc.2 ./release-notes.txt" + echo + echo "HINT: use 'git diff ...HEAD' to build the release notes" + echo + exit 2 +} + +function die { + echo "[ERROR] $@" + echo + exit 1 +} + +if [ $# -lt 2 ]; then + help +fi + +VERSION=$1 +RELEASE_NOTES=$2 +FORCE_TAG=$3 + +VERSION_TAG="v$VERSION" + +echo "-> Verifying Local Directory for Release" + +if [ -z "`which $POD`" ]; then + die "Cocoapods is required to produce a release. Aborting." +fi +echo " > Cocoapods is installed" + +echo " > Is this a reasonable tag?" + +echo $VERSION_TAG | grep -q "^vv" +if [ $? -eq 0 ]; then + die "This tag ($VERSION) is an incorrect format. You should remove the 'v' prefix." +fi + +echo $VERSION_TAG | grep -q -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" +if [ $? -ne 0 ]; then + die "This tag ($VERSION) is an incorrect format. It should be in 'v{MAJOR}.{MINOR}.{PATCH}(-{PRERELEASE_NAME}.{PRERELEASE_VERSION})' form." +fi + +echo " > Is this version ($VERSION) unique?" +git describe --exact-match "$VERSION_TAG" > /dev/null 2>&1 +if [ $? -eq 0 ]; then + if [ -z "$FORCE_TAG" ]; then + die "This tag ($VERSION) already exists. Aborting. Append '-f' to override" + else + echo " > NO, but force was specified." + fi +else + echo " > Yes, tag is unique" +fi + +if [ ! -f "$RELEASE_NOTES" ]; then + echo " > Failed to find $RELEASE_NOTES. Prompting editor" + RELEASE_NOTES=.release-changes + LATEST_TAG=`git for-each-ref refs/tags --sort=-refname --format="%(refname:short)" | grep -E "^v\d+\.\d+\.\d+(-\w+(\.\d)?)?\$" | ruby -e 'puts STDIN.read.split("\n").sort { |a,b| Gem::Version.new(a.gsub(/^v/, "")) <=> Gem::Version.new(b.gsub(/^v/, "")) }.last'` + echo " > Latest tag ${LATEST_TAG}" + echo "${POD_NAME} v$VERSION" > $RELEASE_NOTES + echo "================" >> $RELEASE_NOTES + echo >> $RELEASE_NOTES + echo "# Changelog from ${LATEST_TAG}..HEAD" >> $RELEASE_NOTES + git log ${LATEST_TAG}..HEAD | sed -e 's/^/# /' >> $RELEASE_NOTES + $EDITOR $RELEASE_NOTES + diff -q $RELEASE_NOTES ${RELEASE_NOTES}.backup > /dev/null 2>&1 + STATUS=$? + rm ${RELEASE_NOTES}.backup + if [ $STATUS -eq 0 ]; then + rm $RELEASE_NOTES + die "No changes in release notes file. Aborting." + fi +fi +echo " > Release notes: $RELEASE_NOTES" + +if [ ! -f "$PODSPEC" ]; then + die "Cannot find podspec: $PODSPEC. Aborting." +fi +echo " > Podspec exists" + +git config --get user.signingkey > /dev/null || { + echo "[ERROR] No PGP found to sign tag. Aborting." + echo + echo " Creating a release requires signing the tag for security purposes. This allows users to verify the git cloned tree is from a trusted source." + echo " From a security perspective, it is not considered safe to trust the commits (including Author & Signed-off fields). It is easy for any" + echo " intermediate between you and the end-users to modify the git repository." + echo + echo " While not all users may choose to verify the PGP key for tagged releases. It is a good measure to ensure 'this is an official release'" + echo " from the official maintainers." + echo + echo " If you're creating your PGP key for the first time, use RSA with at least 4096 bits." + echo + echo "Related resources:" + echo " - Configuring your system for PGP: https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work" + echo " - Why: http://programmers.stackexchange.com/questions/212192/what-are-the-advantages-and-disadvantages-of-cryptographically-signing-commits-a" + echo + exit 2 +} +echo " > Found PGP key for git" + +# Verify cocoapods trunk ownership +pod trunk me | grep -q "$POD_NAME" || die "You do not have access to pod repository $POD_NAME. Aborting." +echo " > Verified ownership to $POD_NAME pod" + + +echo "--- Releasing version $VERSION (tag: $VERSION_TAG)..." + +function restore_podspec { + if [ -f "${PODSPEC}.backup" ]; then + mv -f ${PODSPEC}{.backup,} + fi +} + +echo "-> Ensuring no differences to origin/$REMOTE_BRANCH" +git fetch origin || die "Failed to fetch origin" +git diff --quiet HEAD "origin/$REMOTE_BRANCH" || die "HEAD is not aligned to origin/$REMOTE_BRANCH. Cannot update version safely" + +echo "-> Setting podspec version" +cat "$PODSPEC" | grep 's.version' | grep -q "\"$VERSION\"" +SET_PODSPEC_VERSION=$? +if [ $SET_PODSPEC_VERSION -eq 0 ]; then + echo " > Podspec already set to $VERSION. Skipping." +else + sed -i.backup "s/s.version *= *\".*\"/s.version = \"$VERSION\"/g" "$PODSPEC" || { + restore_podspec + die "Failed to update version in podspec" + } + + git add ${PODSPEC} || { restore_podspec; die "Failed to add ${PODSPEC} to INDEX"; } + git commit -m "Bumping version to $VERSION" || { restore_podspec; die "Failed to push updated version: $VERSION"; } +fi + +if [ -z "$FORCE_TAG" ]; then + echo "-> Tagging version" + git tag -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin" + git push origin "$VERSION_TAG" || die "Failed to push tag '$VERSION_TAG' to origin" +else + echo "-> Tagging version (force)" + git tag -f -s "$VERSION_TAG" -F "$RELEASE_NOTES" || die "Failed to tag version" + echo "-> Pushing tag to origin (force)" + git push origin "$VERSION_TAG" -f || die "Failed to push tag '$VERSION_TAG' to origin" +fi + +if [ $SET_PODSPEC_VERSION -ne 0 ]; then + rm $RELEASE_NOTES + git push origin "$REMOTE_BRANCH" || die "Failed to push to origin" + echo " > Pushed version to origin" +fi + +echo +echo "Pushing to pod trunk..." + +$POD trunk push "$PODSPEC" + +echo +echo "================ Finalizing the Release ================" +echo +echo " - Opening GitHub to mark this as a release..." +echo " - Paste the contents of $RELEASE_NOTES into the release notes. Tweak for Github styling." +echo " - Announce!" + +open "https://github.com/Quick/Quick/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/Quick/script/travis-install-linux b/Carthage/Checkouts/Quick/script/travis-install-linux new file mode 100755 index 0000000..279cd88 --- /dev/null +++ b/Carthage/Checkouts/Quick/script/travis-install-linux @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e + +# See: https://github.com/kylef/swiftenv/wiki/Travis-CI +curl -sL https://gist.github.com/kylef/5c0475ff02b7c7671d2a/raw/621ef9b29bbb852fdfd2e10ed147b321d792c1e4/swiftenv-install.sh | bash diff --git a/Carthage/Checkouts/Quick/script/travis-install-macos b/Carthage/Checkouts/Quick/script/travis-install-macos new file mode 100755 index 0000000..64edf92 --- /dev/null +++ b/Carthage/Checkouts/Quick/script/travis-install-macos @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +set -e + +git submodule update --init --recursive diff --git a/Carthage/Checkouts/Quick/script/travis-script-linux b/Carthage/Checkouts/Quick/script/travis-script-linux new file mode 100755 index 0000000..7a6558d --- /dev/null +++ b/Carthage/Checkouts/Quick/script/travis-script-linux @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +. ~/.swiftenv/init +rake test:swiftpm diff --git a/Carthage/Checkouts/Quick/script/travis-script-macos b/Carthage/Checkouts/Quick/script/travis-script-macos new file mode 100755 index 0000000..ac60f1c --- /dev/null +++ b/Carthage/Checkouts/Quick/script/travis-script-macos @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +if [ "$PODSPEC" ]; then + TASK="podspec:lint" +else + TASK="test:$PLATFORM" +fi + +echo "Executing rake task: $TASK" +rake "$TASK" diff --git a/Carthage/Checkouts/Result/.gitignore b/Carthage/Checkouts/Result/.gitignore new file mode 100644 index 0000000..29471cb --- /dev/null +++ b/Carthage/Checkouts/Result/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +xcuserdata +*.xcuserdatad +*.xccheckout +*.mode* +*.pbxuser + +Carthage/Build +.build diff --git a/Carthage/Checkouts/Result/.swift-version b/Carthage/Checkouts/Result/.swift-version new file mode 100644 index 0000000..7d5c902 --- /dev/null +++ b/Carthage/Checkouts/Result/.swift-version @@ -0,0 +1 @@ +4.1 diff --git a/Carthage/Checkouts/Result/.travis.yml b/Carthage/Checkouts/Result/.travis.yml new file mode 100644 index 0000000..6c0cd1a --- /dev/null +++ b/Carthage/Checkouts/Result/.travis.yml @@ -0,0 +1,62 @@ +branches: + only: + - master + +matrix: + include: + - script: + - set -o pipefail + - xcodebuild $XCODE_ACTION -scheme Result-Mac | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-iOS -sdk iphonesimulator -destination "name=iPhone SE" | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-tvOS -sdk appletvsimulator -destination "name=Apple TV" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + - gem update cocoapods && rm .swift-version && pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode9.2 + language: objective-c + - script: + - set -o pipefail + - xcodebuild $XCODE_ACTION -scheme Result-Mac | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-iOS -sdk iphonesimulator -destination "name=iPhone SE" | xcpretty + - xcodebuild $XCODE_ACTION -scheme Result-tvOS -sdk appletvsimulator -destination "name=Apple TV" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + - rm .swift-version && pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode9.3 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode9.2 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode9.3 + language: objective-c + - script: + - swift --version + - swift build + - swift test + env: + - JOB=Linux + sudo: required + dist: trusty + language: generic + install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + +notifications: + email: false diff --git a/Carthage/Checkouts/Result/CONTRIBUTING.md b/Carthage/Checkouts/Result/CONTRIBUTING.md new file mode 100644 index 0000000..f58c3fa --- /dev/null +++ b/Carthage/Checkouts/Result/CONTRIBUTING.md @@ -0,0 +1,23 @@ +We love that you're interested in contributing to this project! + +To make the process as painless as possible, we have just a couple of guidelines +that should make life easier for everyone involved. + +## Prefer Pull Requests + +If you know exactly how to implement the feature being suggested or fix the bug +being reported, please open a pull request instead of an issue. Pull requests are easier than +patches or inline code blocks for discussing and merging the changes. + +If you can't make the change yourself, please open an issue after making sure +that one isn't already logged. + +## Contributing Code + +Fork this repository, make it awesomer (preferably in a branch named for the +topic), send a pull request! + +All code contributions should match our [coding +conventions](https://github.com/github/swift-style-guide). + +Thanks for contributing! :boom::camel: diff --git a/Carthage/Checkouts/Result/LICENSE b/Carthage/Checkouts/Result/LICENSE new file mode 100644 index 0000000..3026ee1 --- /dev/null +++ b/Carthage/Checkouts/Result/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Rob Rix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Carthage/Checkouts/Result/Package.swift b/Carthage/Checkouts/Result/Package.swift new file mode 100644 index 0000000..c93a688 --- /dev/null +++ b/Carthage/Checkouts/Result/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version:4.0 +import PackageDescription + +let package = Package( + name: "Result", + products: [ + .library(name: "Result", targets: ["Result"]), + ], + targets: [ + .target(name: "Result", dependencies: [], path: "Result"), + .testTarget(name: "ResultTests", dependencies: ["Result"]), + ], + swiftLanguageVersions: [4] +) diff --git a/Carthage/Checkouts/Result/README.md b/Carthage/Checkouts/Result/README.md new file mode 100644 index 0000000..bf85e78 --- /dev/null +++ b/Carthage/Checkouts/Result/README.md @@ -0,0 +1,113 @@ +# Result + +[![Build Status](https://travis-ci.org/antitypical/Result.svg?branch=master)](https://travis-ci.org/antitypical/Result) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![CocoaPods](https://img.shields.io/cocoapods/v/Result.svg)](https://cocoapods.org/) +[![Reference Status](https://www.versioneye.com/objective-c/result/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/result/references) + +This is a Swift µframework providing `Result`. + +`Result` values are either successful (wrapping `Value`) or failed (wrapping `Error`). This is similar to Swift’s native `Optional` type: `success` is like `some`, and `failure` is like `none` except with an associated `Error` value. The addition of an associated `Error` allows errors to be passed along for logging or displaying to the user. + +Using this µframework instead of rolling your own `Result` type allows you to easily interface with other frameworks that also use `Result`. + +## Use + +Use `Result` whenever an operation has the possibility of failure. Consider the following example of a function that tries to extract a `String` for a given key from a JSON `Dictionary`. + +```swift +typealias JSONObject = [String: Any] + +enum JSONError: Error { + case noSuchKey(String) + case typeMismatch +} + +func stringForKey(json: JSONObject, key: String) -> Result { + guard let value = json[key] else { + return .failure(.noSuchKey(key)) + } + + if let value = value as? String { + return .success(value) + } + else { + return .failure(.typeMismatch) + } +} +``` + +This function provides a more robust wrapper around the default subscripting provided by `Dictionary`. Rather than return `Any?`, it returns a `Result` that either contains the `String` value for the given key, or an `ErrorType` detailing what went wrong. + +One simple way to handle a `Result` is to deconstruct it using a `switch` statement. + +```swift +switch stringForKey(json, key: "email") { + +case let .success(email): + print("The email is \(email)") + +case let .failure(.noSuchKey(key)): + print("\(key) is not a valid key") + +case .failure(.typeMismatch): + print("Didn't have the right type") +} +``` + +Using a `switch` statement allows powerful pattern matching, and ensures all possible results are covered. Swift 2.0 offers new ways to deconstruct enums like the `if-case` statement, but be wary as such methods do not ensure errors are handled. + +Other methods available for processing `Result` are detailed in the [API documentation](http://cocoadocs.org/docsets/Result/). + +## Result vs. Throws + +Swift 2.0 introduces error handling via throwing and catching `Error`. `Result` accomplishes the same goal by encapsulating the result instead of hijacking control flow. The `Result` abstraction enables powerful functionality such as `map` and `flatMap`, making `Result` more composable than `throw`. + +Since dealing with APIs that throw is common, you can convert such functions into a `Result` by using the `materialize` method. Conversely, a `Result` can be used to throw an error by calling `dematerialize`. + +## Higher Order Functions + +`map` and `flatMap` operate the same as `Optional.map` and `Optional.flatMap` except they apply to `Result`. + +`map` transforms a `Result` into a `Result` of a new type. It does this by taking a function that transforms the `Value` type into a new value. This transformation is only applied in the case of a `success`. In the case of a `failure`, the associated error is re-wrapped in the new `Result`. + +```swift +// transforms a Result to a Result +let idResult = intForKey(json, key:"id").map { id in String(id) } +``` + +Here, the final result is either the id as a `String`, or carries over the `failure` from the previous result. + +`flatMap` is similar to `map` in that it transforms the `Result` into another `Result`. However, the function passed into `flatMap` must return a `Result`. + +An in depth discussion of `map` and `flatMap` is beyond the scope of this documentation. If you would like a deeper understanding, read about functors and monads. This article is a good place to [start](http://www.javiersoto.me/post/106875422394). + +## Integration + +### Carthage + +1. Add this repository as a submodule and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies. +2. Drag `Result.xcodeproj` into your project or workspace. +3. Link your target against `Result.framework`. +4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Result.) + +### Cocoapods + +```ruby +pod 'Result', '~> 3.0.0' +``` + +### Swift Package Manager + +```swift +import PackageDescription + +let package = Package( + name: "MyProject", + targets: [], + dependencies: [ + .Package(url: "https://github.com/antitypical/Result.git", + majorVersion: 3) + ] +) +``` diff --git a/Carthage/Checkouts/Result/Result.podspec b/Carthage/Checkouts/Result/Result.podspec new file mode 100644 index 0000000..09e59f9 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.podspec @@ -0,0 +1,19 @@ +Pod::Spec.new do |s| + s.name = 'Result' + s.version = '4.0.0' + s.summary = 'Swift type modelling the success/failure of arbitrary operations' + + s.homepage = 'https://github.com/antitypical/Result' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { 'Rob Rix' => 'rob.rix@github.com' } + s.source = { :git => 'https://github.com/antitypical/Result.git', :tag => s.version } + s.source_files = 'Result/*.swift' + s.requires_arc = true + s.ios.deployment_target = '8.0' + s.osx.deployment_target = '10.9' + s.watchos.deployment_target = '2.0' + s.tvos.deployment_target = '9.0' + + s.swift_version = '4.0' + s.cocoapods_version = '>= 1.4.0' +end diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj b/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj new file mode 100644 index 0000000..651d0ca --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj @@ -0,0 +1,1066 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + 57FCDE421BA280DC00130C48 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + 57FCDE561BA2814300130C48 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57FCDE471BA280DC00130C48 /* Result.framework */; }; + CD333EF21ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF31ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF41ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF51ED50550004D9C5D /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF11ED50550004D9C5D /* NoError.swift */; }; + CD333EF71ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EF81ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EF91ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EFA1ED505D7004D9C5D /* AnyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EF61ED505D7004D9C5D /* AnyError.swift */; }; + CD333EFC1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333EFD1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333EFE1ED50699004D9C5D /* NoErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */; }; + CD333F001ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + CD333F011ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + CD333F021ED5074F004D9C5D /* AnyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */; }; + D035799B1B2B788F005D26AE /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D035799E1B2B788F005D26AE /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D454805D1A9572F5009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D45480681A9572F5009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D45480571A9572F5009D7229 /* Result.framework */; }; + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D45480881A957362009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D454807D1A957361009D7229 /* Result.framework */; }; + D45480971A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480981A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D454809A1A9574BB009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93621451B35596200948F2A /* ResultProtocol.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 57FCDE571BA2814A00130C48 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 57FCDE3C1BA280DC00130C48; + remoteInfo = "Result-tvOS"; + }; + D45480691A9572F5009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D45480561A9572F5009D7229; + remoteInfo = Result; + }; + D45480891A957362009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D454807C1A957361009D7229; + remoteInfo = "Result-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 57FCDE471BA280DC00130C48 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CD261ACF1DECFE3400A8863C /* LinuxMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = ../LinuxMain.swift; sourceTree = ""; }; + CD333EF11ED50550004D9C5D /* NoError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoError.swift; sourceTree = ""; }; + CD333EF61ED505D7004D9C5D /* AnyError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyError.swift; sourceTree = ""; }; + CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoErrorTests.swift; sourceTree = ""; }; + CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyErrorTests.swift; sourceTree = ""; }; + D03579A31B2B788F005D26AE /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480571A9572F5009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D454805B1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454805C1A9572F5009D7229 /* Result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Result.h; sourceTree = ""; }; + D45480671A9572F5009D7229 /* Result-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D454806D1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454806E1A9572F5009D7229 /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = ""; }; + D454807D1A957361009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480871A957362009D7229 /* Result-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480961A957465009D7229 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; + E93621451B35596200948F2A /* ResultProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultProtocol.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 57FCDE401BA280DC00130C48 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4E1BA280E000130C48 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE561BA2814300130C48 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799C1B2B788F005D26AE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480531A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480641A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480681A9572F5009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480791A957361009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480841A957362009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480881A957362009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D454804D1A9572F5009D7229 = { + isa = PBXGroup; + children = ( + D45480591A9572F5009D7229 /* Result */, + D454806B1A9572F5009D7229 /* ResultTests */, + D45480581A9572F5009D7229 /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D45480581A9572F5009D7229 /* Products */ = { + isa = PBXGroup; + children = ( + D45480571A9572F5009D7229 /* Result.framework */, + D45480671A9572F5009D7229 /* Result-MacTests.xctest */, + D454807D1A957361009D7229 /* Result.framework */, + D45480871A957362009D7229 /* Result-iOSTests.xctest */, + D03579A31B2B788F005D26AE /* Result.framework */, + 57FCDE471BA280DC00130C48 /* Result.framework */, + 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D45480591A9572F5009D7229 /* Result */ = { + isa = PBXGroup; + children = ( + CD333EF61ED505D7004D9C5D /* AnyError.swift */, + CD333EF11ED50550004D9C5D /* NoError.swift */, + D454805C1A9572F5009D7229 /* Result.h */, + D45480961A957465009D7229 /* Result.swift */, + E93621451B35596200948F2A /* ResultProtocol.swift */, + D454805A1A9572F5009D7229 /* Supporting Files */, + ); + path = Result; + sourceTree = ""; + }; + D454805A1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D454805B1A9572F5009D7229 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D454806B1A9572F5009D7229 /* ResultTests */ = { + isa = PBXGroup; + children = ( + CD333EFF1ED5074F004D9C5D /* AnyErrorTests.swift */, + CD333EFB1ED50699004D9C5D /* NoErrorTests.swift */, + D454806E1A9572F5009D7229 /* ResultTests.swift */, + D454806C1A9572F5009D7229 /* Supporting Files */, + ); + name = ResultTests; + path = Tests/ResultTests; + sourceTree = ""; + }; + D454806C1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D454806D1A9572F5009D7229 /* Info.plist */, + CD261ACF1DECFE3400A8863C /* LinuxMain.swift */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 57FCDE411BA280DC00130C48 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE421BA280DC00130C48 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799D1B2B788F005D26AE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D035799E1B2B788F005D26AE /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480541A9572F5009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454805D1A9572F5009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807A1A957361009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454809A1A9574BB009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 57FCDE3C1BA280DC00130C48 /* Result-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57FCDE441BA280DC00130C48 /* Build configuration list for PBXNativeTarget "Result-tvOS" */; + buildPhases = ( + 57FCDE3D1BA280DC00130C48 /* Sources */, + 57FCDE401BA280DC00130C48 /* Frameworks */, + 57FCDE411BA280DC00130C48 /* Headers */, + 57FCDE431BA280DC00130C48 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-tvOS"; + productName = "Result-iOS"; + productReference = 57FCDE471BA280DC00130C48 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + 57FCDE491BA280E000130C48 /* Result-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57FCDE511BA280E000130C48 /* Build configuration list for PBXNativeTarget "Result-tvOSTests" */; + buildPhases = ( + 57FCDE4C1BA280E000130C48 /* Sources */, + 57FCDE4E1BA280E000130C48 /* Frameworks */, + 57FCDE501BA280E000130C48 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 57FCDE581BA2814A00130C48 /* PBXTargetDependency */, + ); + name = "Result-tvOSTests"; + productName = "Result-iOSTests"; + productReference = 57FCDE541BA280E000130C48 /* Result-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D03579991B2B788F005D26AE /* Result-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D03579A01B2B788F005D26AE /* Build configuration list for PBXNativeTarget "Result-watchOS" */; + buildPhases = ( + D035799A1B2B788F005D26AE /* Sources */, + D035799C1B2B788F005D26AE /* Frameworks */, + D035799D1B2B788F005D26AE /* Headers */, + D035799F1B2B788F005D26AE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-watchOS"; + productName = Result; + productReference = D03579A31B2B788F005D26AE /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480561A9572F5009D7229 /* Result-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */; + buildPhases = ( + D45480521A9572F5009D7229 /* Sources */, + D45480531A9572F5009D7229 /* Frameworks */, + D45480541A9572F5009D7229 /* Headers */, + D45480551A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-Mac"; + productName = Result; + productReference = D45480571A9572F5009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480661A9572F5009D7229 /* Result-MacTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */; + buildPhases = ( + D45480631A9572F5009D7229 /* Sources */, + D45480641A9572F5009D7229 /* Frameworks */, + D45480651A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454806A1A9572F5009D7229 /* PBXTargetDependency */, + ); + name = "Result-MacTests"; + productName = ResultTests; + productReference = D45480671A9572F5009D7229 /* Result-MacTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D454807C1A957361009D7229 /* Result-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */; + buildPhases = ( + D45480781A957361009D7229 /* Sources */, + D45480791A957361009D7229 /* Frameworks */, + D454807A1A957361009D7229 /* Headers */, + D454807B1A957361009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-iOS"; + productName = "Result-iOS"; + productReference = D454807D1A957361009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480861A957362009D7229 /* Result-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */; + buildPhases = ( + D45480831A957362009D7229 /* Sources */, + D45480841A957362009D7229 /* Frameworks */, + D45480851A957362009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454808A1A957362009D7229 /* PBXTargetDependency */, + ); + name = "Result-iOSTests"; + productName = "Result-iOSTests"; + productReference = D45480871A957362009D7229 /* Result-iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D454804E1A9572F5009D7229 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + 57FCDE3C1BA280DC00130C48 = { + LastSwiftMigration = 0920; + }; + 57FCDE491BA280E000130C48 = { + LastSwiftMigration = 0920; + }; + D03579991B2B788F005D26AE = { + LastSwiftMigration = 0920; + }; + D45480561A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0900; + }; + D45480661A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0900; + }; + D454807C1A957361009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0920; + }; + D45480861A957362009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0920; + }; + }; + }; + buildConfigurationList = D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D454804D1A9572F5009D7229; + productRefGroup = D45480581A9572F5009D7229 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D45480561A9572F5009D7229 /* Result-Mac */, + D45480661A9572F5009D7229 /* Result-MacTests */, + D454807C1A957361009D7229 /* Result-iOS */, + D45480861A957362009D7229 /* Result-iOSTests */, + 57FCDE3C1BA280DC00130C48 /* Result-tvOS */, + 57FCDE491BA280E000130C48 /* Result-tvOSTests */, + D03579991B2B788F005D26AE /* Result-watchOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 57FCDE431BA280DC00130C48 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE501BA280E000130C48 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799F1B2B788F005D26AE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480551A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480651A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807B1A957361009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480851A957362009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 57FCDE3D1BA280DC00130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF41ED50550004D9C5D /* NoError.swift in Sources */, + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */, + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */, + CD333EF91ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4C1BA280E000130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */, + CD333F021ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFE1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799A1B2B788F005D26AE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF51ED50550004D9C5D /* NoError.swift in Sources */, + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */, + D035799B1B2B788F005D26AE /* Result.swift in Sources */, + CD333EFA1ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480521A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF21ED50550004D9C5D /* NoError.swift in Sources */, + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480971A957465009D7229 /* Result.swift in Sources */, + CD333EF71ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480631A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */, + CD333F001ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFC1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480781A957361009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD333EF31ED50550004D9C5D /* NoError.swift in Sources */, + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480981A957465009D7229 /* Result.swift in Sources */, + CD333EF81ED505D7004D9C5D /* AnyError.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480831A957362009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */, + CD333F011ED5074F004D9C5D /* AnyErrorTests.swift in Sources */, + CD333EFD1ED50699004D9C5D /* NoErrorTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 57FCDE581BA2814A00130C48 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 57FCDE3C1BA280DC00130C48 /* Result-tvOS */; + targetProxy = 57FCDE571BA2814A00130C48 /* PBXContainerItemProxy */; + }; + D454806A1A9572F5009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D45480561A9572F5009D7229 /* Result-Mac */; + targetProxy = D45480691A9572F5009D7229 /* PBXContainerItemProxy */; + }; + D454808A1A957362009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D454807C1A957361009D7229 /* Result-iOS */; + targetProxy = D45480891A957362009D7229 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 57FCDE451BA280DC00130C48 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=appletvsimulator*]" = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 57FCDE461BA280DC00130C48 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=appletvsimulator*]" = ""; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 57FCDE521BA280E000130C48 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + }; + name = Debug; + }; + 57FCDE531BA280E000130C48 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D03579A11B2B788F005D26AE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchsimulator*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = watchos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + D03579A21B2B788F005D26AE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchsimulator*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = watchos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + D45480701A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + D45480711A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + 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.9; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.$(PRODUCT_NAME:rfc1034identifier)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + D45480731A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + D45480741A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + D45480761A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D45480771A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D45480901A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D45480911A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D45480921A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + D45480931A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = Tests/ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 57FCDE441BA280DC00130C48 /* Build configuration list for PBXNativeTarget "Result-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 57FCDE451BA280DC00130C48 /* Debug */, + 57FCDE461BA280DC00130C48 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 57FCDE511BA280E000130C48 /* Build configuration list for PBXNativeTarget "Result-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 57FCDE521BA280E000130C48 /* Debug */, + 57FCDE531BA280E000130C48 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D03579A01B2B788F005D26AE /* Build configuration list for PBXNativeTarget "Result-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D03579A11B2B788F005D26AE /* Debug */, + D03579A21B2B788F005D26AE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480701A9572F5009D7229 /* Debug */, + D45480711A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480731A9572F5009D7229 /* Debug */, + D45480741A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480761A9572F5009D7229 /* Debug */, + D45480771A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480901A957362009D7229 /* Debug */, + D45480911A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480921A957362009D7229 /* Debug */, + D45480931A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D454804E1A9572F5009D7229 /* Project object */; +} diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..10cf711 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme new file mode 100644 index 0000000..eee4090 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme new file mode 100644 index 0000000..d669e9b --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme new file mode 100644 index 0000000..e337798 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme new file mode 100644 index 0000000..59371bc --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result/AnyError.swift b/Carthage/Checkouts/Result/Result/AnyError.swift new file mode 100644 index 0000000..ee018d2 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/AnyError.swift @@ -0,0 +1,46 @@ +import Foundation + +/// A type-erased error which wraps an arbitrary error instance. This should be +/// useful for generic contexts. +public struct AnyError: Swift.Error { + /// The underlying error. + public let error: Swift.Error + + public init(_ error: Swift.Error) { + if let anyError = error as? AnyError { + self = anyError + } else { + self.error = error + } + } +} + +extension AnyError: ErrorConvertible { + public static func error(from error: Error) -> AnyError { + return AnyError(error) + } +} + +extension AnyError: CustomStringConvertible { + public var description: String { + return String(describing: error) + } +} + +extension AnyError: LocalizedError { + public var errorDescription: String? { + return error.localizedDescription + } + + public var failureReason: String? { + return (error as? LocalizedError)?.failureReason + } + + public var helpAnchor: String? { + return (error as? LocalizedError)?.helpAnchor + } + + public var recoverySuggestion: String? { + return (error as? LocalizedError)?.recoverySuggestion + } +} diff --git a/Carthage/Checkouts/Result/Result/Info.plist b/Carthage/Checkouts/Result/Result/Info.plist new file mode 100644 index 0000000..52221a4 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Rob Rix. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Result/Result/NoError.swift b/Carthage/Checkouts/Result/Result/NoError.swift new file mode 100644 index 0000000..a919f51 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/NoError.swift @@ -0,0 +1,10 @@ +/// An “error” that is impossible to construct. +/// +/// This can be used to describe `Result`s where failures will never +/// be generated. For example, `Result` describes a result that +/// contains an `Int`eger and is guaranteed never to be a `failure`. +public enum NoError: Swift.Error, Equatable { + public static func ==(lhs: NoError, rhs: NoError) -> Bool { + return true + } +} diff --git a/Carthage/Checkouts/Result/Result/Result.h b/Carthage/Checkouts/Result/Result/Result.h new file mode 100644 index 0000000..4742701 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Result.h @@ -0,0 +1,8 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// Project version number for Result. +extern double ResultVersionNumber; + +/// Project version string for Result. +extern const unsigned char ResultVersionString[]; + diff --git a/Carthage/Checkouts/Result/Result/Result.swift b/Carthage/Checkouts/Result/Result/Result.swift new file mode 100644 index 0000000..de0330a --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Result.swift @@ -0,0 +1,196 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// An enum representing either a failure with an explanatory error, or a success with a result value. +public enum Result: ResultProtocol, CustomStringConvertible, CustomDebugStringConvertible { + case success(Value) + case failure(Error) + + // MARK: Constructors + + /// Constructs a success wrapping a `value`. + public init(value: Value) { + self = .success(value) + } + + /// Constructs a failure wrapping an `error`. + public init(error: Error) { + self = .failure(error) + } + + /// Constructs a result from an `Optional`, failing with `Error` if `nil`. + public init(_ value: Value?, failWith: @autoclosure () -> Error) { + self = value.map(Result.success) ?? .failure(failWith()) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(_ f: @autoclosure () throws -> Value) { + self.init(attempt: f) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(attempt f: () throws -> Value) { + do { + self = .success(try f()) + } catch var error { + if Error.self == AnyError.self { + error = AnyError(error) + } + self = .failure(error as! Error) + } + } + + // MARK: Deconstruction + + /// Returns the value from `success` Results or `throw`s the error. + public func dematerialize() throws -> Value { + switch self { + case let .success(value): + return value + case let .failure(error): + throw error + } + } + + /// Case analysis for Result. + /// + /// Returns the value produced by applying `ifFailure` to `failure` Results, or `ifSuccess` to `success` Results. + public func analysis(ifSuccess: (Value) -> Result, ifFailure: (Error) -> Result) -> Result { + switch self { + case let .success(value): + return ifSuccess(value) + case let .failure(value): + return ifFailure(value) + } + } + + // MARK: Errors + + /// The domain for errors constructed by Result. + public static var errorDomain: String { return "com.antitypical.Result" } + + /// The userInfo key for source functions in errors constructed by Result. + public static var functionKey: String { return "\(errorDomain).function" } + + /// The userInfo key for source file paths in errors constructed by Result. + public static var fileKey: String { return "\(errorDomain).file" } + + /// The userInfo key for source file line numbers in errors constructed by Result. + public static var lineKey: String { return "\(errorDomain).line" } + + /// Constructs an error. + public static func error(_ message: String? = nil, function: String = #function, file: String = #file, line: Int = #line) -> NSError { + var userInfo: [String: Any] = [ + functionKey: function, + fileKey: file, + lineKey: line, + ] + + if let message = message { + userInfo[NSLocalizedDescriptionKey] = message + } + + return NSError(domain: errorDomain, code: 0, userInfo: userInfo) + } + + + // MARK: CustomStringConvertible + + public var description: String { + switch self { + case let .success(value): return ".success(\(value))" + case let .failure(error): return ".failure(\(error))" + } + } + + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + return description + } + + // MARK: ResultProtocol + public var result: Result { + return self + } +} + +extension Result where Error == AnyError { + /// Constructs a result from an expression that uses `throw`, failing with `AnyError` if throws. + public init(_ f: @autoclosure () throws -> Value) { + self.init(attempt: f) + } + + /// Constructs a result from a closure that uses `throw`, failing with `AnyError` if throws. + public init(attempt f: () throws -> Value) { + do { + self = .success(try f()) + } catch { + self = .failure(AnyError(error)) + } + } +} + +// MARK: - Derive result from failable closure + +@available(*, deprecated, renamed: "Result.init(attempt:)") +public func materialize(_ f: () throws -> T) -> Result { + return Result(attempt: f) +} + +@available(*, deprecated, renamed: "Result.init(_:)") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + return Result(f) +} + +// MARK: - ErrorConvertible conformance + +extension NSError: ErrorConvertible { + public static func error(from error: Swift.Error) -> Self { + func cast(_ error: Swift.Error) -> T { + return error as! T + } + + return cast(error) + } +} + +// MARK: - migration support + +@available(*, unavailable, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: () throws -> T) -> Result { + fatalError() +} + +@available(*, unavailable, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + fatalError() +} + +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + +/// Constructs a `Result` with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.: +/// +/// Result.try { NSData(contentsOfURL: URL, options: .dataReadingMapped, error: $0) } +@available(*, unavailable, message: "This has been removed. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.") +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> T?) -> Result { + fatalError() +} + +/// Constructs a `Result` with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.: +/// +/// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) } +@available(*, unavailable, message: "This has been removed. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.") +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> Bool) -> Result<(), NSError> { + fatalError() +} + +#endif + +// MARK: - + +import Foundation diff --git a/Carthage/Checkouts/Result/Result/ResultProtocol.swift b/Carthage/Checkouts/Result/Result/ResultProtocol.swift new file mode 100644 index 0000000..703ad89 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/ResultProtocol.swift @@ -0,0 +1,152 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// A protocol that can be used to constrain associated types as `Result`. +public protocol ResultProtocol { + associatedtype Value + associatedtype Error: Swift.Error + + init(value: Value) + init(error: Error) + + var result: Result { get } +} + +public extension Result { + /// Returns the value if self represents a success, `nil` otherwise. + public var value: Value? { + switch self { + case let .success(value): return value + case .failure: return nil + } + } + + /// Returns the error if self represents a failure, `nil` otherwise. + public var error: Error? { + switch self { + case .success: return nil + case let .failure(error): return error + } + } + + /// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors. + public func map(_ transform: (Value) -> U) -> Result { + return flatMap { .success(transform($0)) } + } + + /// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. + public func flatMap(_ transform: (Value) -> Result) -> Result { + switch self { + case let .success(value): return transform(value) + case let .failure(error): return .failure(error) + } + } + + /// Returns a Result with a tuple of the receiver and `other` values if both + /// are `Success`es, or re-wrapping the error of the earlier `Failure`. + public func fanout(_ other: @autoclosure () -> Result) -> Result<(Value, U), Error> { + return self.flatMap { left in other().map { right in (left, right) } } + } + + /// Returns a new Result by mapping `Failure`'s values using `transform`, or re-wrapping `Success`es’ values. + public func mapError(_ transform: (Error) -> Error2) -> Result { + return flatMapError { .failure(transform($0)) } + } + + /// Returns the result of applying `transform` to `Failure`’s errors, or re-wrapping `Success`es’ values. + public func flatMapError(_ transform: (Error) -> Result) -> Result { + switch self { + case let .success(value): return .success(value) + case let .failure(error): return transform(error) + } + } + + /// Returns a new Result by mapping `Success`es’ values using `success`, and by mapping `Failure`'s values using `failure`. + public func bimap(success: (Value) -> U, failure: (Error) -> Error2) -> Result { + switch self { + case let .success(value): return .success(success(value)) + case let .failure(error): return .failure(failure(error)) + } + } +} + +public extension Result { + + // MARK: Higher-order functions + + /// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??` + public func recover(_ value: @autoclosure () -> Value) -> Value { + return self.value ?? value() + } + + /// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??` + public func recover(with result: @autoclosure () -> Result) -> Result { + switch self { + case .success: return self + case .failure: return result() + } + } +} + +/// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s. +public protocol ErrorConvertible: Swift.Error { + static func error(from error: Swift.Error) -> Self +} + +public extension Result where Error: ErrorConvertible { + + /// Returns the result of applying `transform` to `Success`es’ values, or wrapping thrown errors. + public func tryMap(_ transform: (Value) throws -> U) -> Result { + return flatMap { value in + do { + return .success(try transform(value)) + } + catch { + let convertedError = Error.error(from: error) + // Revisit this in a future version of Swift. https://twitter.com/jckarter/status/672931114944696321 + return .failure(convertedError) + } + } + } +} + +// MARK: - Operators + +extension Result where Value: Equatable, Error: Equatable { + /// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal. + public static func ==(left: Result, right: Result) -> Bool { + if let left = left.value, let right = right.value { + return left == right + } else if let left = left.error, let right = right.error { + return left == right + } + return false + } +} + +#if swift(>=4.1) + extension Result: Equatable where Value: Equatable, Error: Equatable { } +#else + extension Result where Value: Equatable, Error: Equatable { + /// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. + public static func !=(left: Result, right: Result) -> Bool { + return !(left == right) + } + } +#endif + +extension Result { + /// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. + public static func ??(left: Result, right: @autoclosure () -> Value) -> Value { + return left.recover(right()) + } + + /// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. + public static func ??(left: Result, right: @autoclosure () -> Result) -> Result { + return left.recover(with: right()) + } +} + +// MARK: - migration support + +@available(*, unavailable, renamed: "ErrorConvertible") +public protocol ErrorProtocolConvertible: ErrorConvertible {} diff --git a/Carthage/Checkouts/Result/Tests/LinuxMain.swift b/Carthage/Checkouts/Result/Tests/LinuxMain.swift new file mode 100644 index 0000000..ec2c509 --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +import ResultTests + +var tests = [XCTestCaseEntry]() +tests += ResultTests.__allTests() + +XCTMain(tests) diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift b/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift new file mode 100644 index 0000000..65a2661 --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/AnyErrorTests.swift @@ -0,0 +1,12 @@ +import Foundation +import XCTest +import Result + +final class AnyErrorTests: XCTestCase { + func testAnyError() { + let error = Error.a + let anyErrorFromError = AnyError(error) + let anyErrorFromAnyError = AnyError(anyErrorFromError) + XCTAssertTrue(anyErrorFromError == anyErrorFromAnyError) + } +} diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist b/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist new file mode 100644 index 0000000..18f6dd6 --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift b/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift new file mode 100644 index 0000000..61bc107 --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/NoErrorTests.swift @@ -0,0 +1,11 @@ +import Foundation +import XCTest +import Result + +final class NoErrorTests: XCTestCase { + func testEquatable() { + let foo = Result(1) + let bar = Result(1) + XCTAssertTrue(foo == bar) + } +} diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift b/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift new file mode 100644 index 0000000..f7fb38c --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift @@ -0,0 +1,256 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +final class ResultTests: XCTestCase { + func testMapTransformsSuccesses() { + XCTAssertEqual(success.map { $0.count } ?? 0, 7) + } + + func testMapRewrapsFailures() { + XCTAssertEqual(failure.map { $0.count } ?? 0, 0) + } + + func testInitOptionalSuccess() { + XCTAssert(Result("success" as String?, failWith: error) == success) + } + + func testInitOptionalFailure() { + XCTAssert(Result(nil, failWith: error) == failure) + } + + func testFanout() { + let resultSuccess = success.fanout(success) + if let (x, y) = resultSuccess.value { + XCTAssertTrue(x == "success" && y == "success") + } else { + XCTFail() + } + + let resultFailureBoth = failure.fanout(failure2) + XCTAssert(resultFailureBoth.error == error) + + let resultFailureLeft = failure.fanout(success) + XCTAssert(resultFailureLeft.error == error) + + let resultFailureRight = success.fanout(failure2) + XCTAssert(resultFailureRight.error == error2) + } + + func testBimapTransformsSuccesses() { + XCTAssertEqual(success.bimap( + success: { $0.count }, + failure: { $0 } + ) ?? 0, 7) + } + + func testBimapTransformsFailures() { + XCTAssert(failure.bimap( + success: { $0 }, + failure: { _ in error2 } + ) == failure2) + } + + // MARK: Errors + + func testErrorsIncludeTheSourceFile() { + let file = #file + XCTAssert(Result<(), NSError>.error().file == file) + } + + func testErrorsIncludeTheSourceLine() { + let (line, error) = (#line, Result<(), NSError>.error()) + XCTAssertEqual(error.line ?? -1, line) + } + + func testErrorsIncludeTheCallingFunction() { + let function = #function + XCTAssert(Result<(), NSError>.error().function == function) + } + + func testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError() { + XCTAssertEqual(error.errorDescription, "localized description") + XCTAssertEqual(error.localizedDescription, "localized description") + XCTAssertEqual(error3.errorDescription, "localized description") + XCTAssertEqual(error3.localizedDescription, "localized description") + } + + func testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError() { + XCTAssertEqual(error.failureReason, "failure reason") + } + + func testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError() { + XCTAssertEqual(error.recoverySuggestion, "recovery suggestion") + } + + func testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError() { + XCTAssertEqual(error.helpAnchor, "help anchor") + } + + // MARK: Try - Catch + + func testTryCatchProducesSuccesses() { + let result: Result = Result(try tryIsSuccess("success")) + XCTAssert(result == success) + } + + func testTryCatchProducesFailures() { + let result: Result = Result(try tryIsSuccess(nil)) + XCTAssert(result.error == error) + } + + func testTryCatchWithFunctionProducesSuccesses() { + let function = { try tryIsSuccess("success") } + + let result: Result = Result(attempt: function) + XCTAssert(result == success) + } + + func testTryCatchWithFunctionCatchProducesFailures() { + let function = { try tryIsSuccess(nil) } + + let result: Result = Result(attempt: function) + XCTAssert(result.error == error) + } + + func testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures() { + let nsError = NSError(domain: "", code: 0) + let function: () throws -> String = { throw nsError } + + let result: Result = Result(attempt: function) + XCTAssert(result.error == AnyError(nsError)) + } + + func testMaterializeProducesSuccesses() { + let result1: Result = Result(try tryIsSuccess("success")) + XCTAssert(result1 == success) + + let result2: Result = Result(attempt: { try tryIsSuccess("success") }) + XCTAssert(result2 == success) + } + + func testMaterializeProducesFailures() { + let result1: Result = Result(try tryIsSuccess(nil)) + XCTAssert(result1.error == error) + + let result2: Result = Result(attempt: { try tryIsSuccess(nil) }) + XCTAssert(result2.error == error) + } + + func testMaterializeInferrence() { + let result = Result(attempt: { try tryIsSuccess(nil) }) + XCTAssert((type(of: result) as Any.Type) is Result.Type) + } + + // MARK: Recover + + func testRecoverProducesLeftForLeftSuccess() { + let left = Result.success("left") + XCTAssertEqual(left.recover("right"), "left") + } + + func testRecoverProducesRightForLeftFailure() { + let left = Result.failure(Error.a) + XCTAssertEqual(left.recover("right"), "right") + } + + // MARK: Recover With + + func testRecoverWithProducesLeftForLeftSuccess() { + let left = Result.success("left") + let right = Result.success("right") + + XCTAssertEqual(left.recover(with: right).value, "left") + } + + func testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess() { + struct Error: Swift.Error {} + + let left = Result.failure(Error()) + let right = Result.success("right") + + XCTAssertEqual(left.recover(with: right).value, "right") + } + + func testRecoverWithProducesRightFailureForLeftFailureAndRightFailure() { + enum Error: Swift.Error { case left, right } + + let left = Result.failure(.left) + let right = Result.failure(.right) + + XCTAssertEqual(left.recover(with: right).error, .right) + } + + func testTryMapProducesSuccess() { + let result = success.tryMap(tryIsSuccess) + XCTAssert(result == success) + } + + func testTryMapProducesFailure() { + let result = Result.success("fail").tryMap(tryIsSuccess) + XCTAssert(result == failure) + } +} + + +// MARK: - Fixtures + +enum Error: Swift.Error, LocalizedError { + case a, b + + var errorDescription: String? { + return "localized description" + } + + var failureReason: String? { + return "failure reason" + } + + var helpAnchor: String? { + return "help anchor" + } + + var recoverySuggestion: String? { + return "recovery suggestion" + } +} + +let success = Result.success("success") +let error = AnyError(Error.a) +let error2 = AnyError(Error.b) +let error3 = AnyError(NSError(domain: "Result", code: 42, userInfo: [NSLocalizedDescriptionKey: "localized description"])) +let failure = Result.failure(error) +let failure2 = Result.failure(error2) + +// MARK: - Helpers + +extension AnyError: Equatable { + public static func ==(lhs: AnyError, rhs: AnyError) -> Bool { + return lhs.error._code == rhs.error._code + && lhs.error._domain == rhs.error._domain + } +} + +func tryIsSuccess(_ text: String?) throws -> String { + guard let text = text, text == "success" else { + throw error + } + + return text +} + +extension NSError { + var function: String? { + return userInfo[Result<(), NSError>.functionKey] as? String + } + + var file: String? { + return userInfo[Result<(), NSError>.fileKey] as? String + } + + var line: Int? { + return userInfo[Result<(), NSError>.lineKey] as? Int + } +} + +import Foundation +import Result +import XCTest diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift b/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift new file mode 100644 index 0000000..7366acf --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/XCTestManifests.swift @@ -0,0 +1,57 @@ +import XCTest + +extension AnyErrorTests { + static let __allTests = [ + ("testAnyError", testAnyError), + ] +} + +extension NoErrorTests { + static let __allTests = [ + ("testEquatable", testEquatable), + ] +} + +extension ResultTests { + static let __allTests = [ + ("testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError", testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError), + ("testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError", testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError), + ("testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError", testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError), + ("testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError", testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError), + ("testBimapTransformsFailures", testBimapTransformsFailures), + ("testBimapTransformsSuccesses", testBimapTransformsSuccesses), + ("testErrorsIncludeTheCallingFunction", testErrorsIncludeTheCallingFunction), + ("testErrorsIncludeTheSourceFile", testErrorsIncludeTheSourceFile), + ("testErrorsIncludeTheSourceLine", testErrorsIncludeTheSourceLine), + ("testFanout", testFanout), + ("testInitOptionalFailure", testInitOptionalFailure), + ("testInitOptionalSuccess", testInitOptionalSuccess), + ("testMapRewrapsFailures", testMapRewrapsFailures), + ("testMapTransformsSuccesses", testMapTransformsSuccesses), + ("testMaterializeInferrence", testMaterializeInferrence), + ("testMaterializeProducesFailures", testMaterializeProducesFailures), + ("testMaterializeProducesSuccesses", testMaterializeProducesSuccesses), + ("testRecoverProducesLeftForLeftSuccess", testRecoverProducesLeftForLeftSuccess), + ("testRecoverProducesRightForLeftFailure", testRecoverProducesRightForLeftFailure), + ("testRecoverWithProducesLeftForLeftSuccess", testRecoverWithProducesLeftForLeftSuccess), + ("testRecoverWithProducesRightFailureForLeftFailureAndRightFailure", testRecoverWithProducesRightFailureForLeftFailureAndRightFailure), + ("testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess", testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess), + ("testTryCatchProducesFailures", testTryCatchProducesFailures), + ("testTryCatchProducesSuccesses", testTryCatchProducesSuccesses), + ("testTryCatchWithFunctionCatchProducesFailures", testTryCatchWithFunctionCatchProducesFailures), + ("testTryCatchWithFunctionProducesSuccesses", testTryCatchWithFunctionProducesSuccesses), + ("testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures", testTryCatchWithFunctionThrowingNonAnyErrorCanProducesAnyErrorFailures), + ("testTryMapProducesFailure", testTryMapProducesFailure), + ("testTryMapProducesSuccess", testTryMapProducesSuccess), + ] +} + +#if !os(macOS) +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(AnyErrorTests.__allTests), + testCase(NoErrorTests.__allTests), + testCase(ResultTests.__allTests), + ] +} +#endif